Ограничение количества отображаемых результатов при использовании ngRepeat

148

Я нахожу учебники по AngularJS трудными для понимания; этот рассказывает мне о создании приложения, которое отображает телефоны. Я на шаге 5, и я подумал, что в качестве эксперимента я попытаюсь позволить пользователям указать, сколько они хотели бы показать. Вид выглядит так:

<body ng-controller="PhoneListCtrl">

  <div class="container-fluid">
    <div class="row-fluid">
      <div class="span2">
        <!--Sidebar content-->

        Search: <input ng-model="query">
        How Many: <input ng-model="quantity">
        Sort by:
        <select ng-model="orderProp">
          <option value="name">Alphabetical</option>
          <option value="age">Newest</option>
        </select>

      </div>
      <div class="span10">
        <!--Body content-->

        <ul class="phones">
          <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
            {{phone.name}}
            <p>{{phone.snippet}}</p>
          </li>
        </ul>

      </div>
    </div>
  </div>
</body>

Я добавил эту строку, где пользователи могут ввести, сколько результатов они хотят показать:

How Many: <input ng-model="quantity">

Вот мой контроллер:

function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data.splice(0, 'quantity');
  });

  $scope.orderProp = 'age';
  $scope.quantity = 5;
}

Важная строка:

$scope.phones = data.splice(0, 'quantity');

Я могу жестко ввести число, чтобы показать, сколько телефонов должно быть показано. Если я вставлю 5, 5 будет показано. Все, что я хочу сделать, это прочитать число в этом входе из представления и поместить его в data.spliceстроку. Я пробовал с и без кавычек, и ни одна из них не работает. Как мне это сделать?

Капитан Стэк
источник

Ответы:

345

Чуть более «Angular way» будет использовать простой limitToфильтр, как это предусмотрено Angular:

<ul class="phones">
  <li ng-repeat="phone in phones | filter:query | orderBy:orderProp | limitTo:quantity">
    {{phone.name}}
    <p>{{phone.snippet}}</p>
  </li>
</ul>
app.controller('PhoneListCtrl', function($scope, $http) {
    $http.get('phones.json').then(
      function(phones){
        $scope.phones = phones.data;
      }
    );
    $scope.orderProp = 'age';
    $scope.quantity = 5;
  }
);

PLUNKER

Стьюи
источник
54
Стоит отметить - и сэкономить кому-то еще несколько минут - что если вы используете «отслеживание», оно ДОЛЖНО быть последним после фильтров.
stephan.com
3
Есть ли способ получить количество доступных элементов при использовании filter и limitTo? Я хотел бы использовать, limitToно предоставить кнопку «Загрузить еще», чтобы увеличить лимит. Это должно отображаться, только если доступно больше записей.
Тим Бюте
Что такое filter:query?
bigpony
@defmx по вопросу ОП, queryисходит отSearch: <input ng-model="query">
jusopi
45

Немного опоздал на вечеринку, но у меня это сработало. Надеюсь, кто-то еще найдет это полезным.

<div ng-repeat="video in videos" ng-if="$index < 3">
    ...
</div>
couzzi
источник
2
Я подозреваю, что это будет менее эффективно, чем использование limitToFilter, если это большой массив, потому что каждый элемент, вероятно, должен быть оценен
rom99
3
У меня был сценарий, в котором я хотел показать 6 элементов из резервного массива и многое другое. Использование ng-if="$index < 6"позволило мне показать только первые 6, сохраняя весь массив для поиска (у меня есть фильтр в сочетании с полем поиска).
Йерун Ванневел
Это не предел, это скрыть весь результат, если считать больше 3.
fdrv
@ Jek-fdrv - Нет, ng-ifв этом случае не будет отображаться элемент DOM повторителя, значение которого $indexбольше, чем 3. если $indexв повторителе есть 0, 1, or 2, условие trueи узлы DOM созданы. ng-ifотличается от ng-hideтого, что элементы не добавляются в DOM.
Couzzi
2

сохранить все ваши данные изначально

function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data.splice(0, 5);
    $scope.allPhones = data;
  });

  $scope.orderProp = 'age';
  $scope.howMany = 5;
  //then here watch the howMany variable on the scope and update the phones array accordingly
  $scope.$watch("howMany", function(newValue, oldValue){
    $scope.phones = $scope.allPhones.splice(0,newValue)
  });
}

EDIT случайно поместил часы за пределы контроллера, он должен был быть внутри.

shaunhusain
источник
2

Вот еще один способ ограничить ваш фильтр на HTML, например, я хочу отобразить 3 списка одновременно, чем я буду использовать limitTo: 3

  <li ng-repeat="phone in phones | limitTo:3">
    <p>Phone Name: {{phone.name}}</p>
  </li>
Ризо
источник
1

Это работает лучше в моем случае, если у вас есть объект или многомерный массив. Будут показаны только первые элементы, остальные будут просто игнорироваться в цикле.

.filter('limitItems', function () {
  return function (items) {
    var result = {}, i = 1;
    angular.forEach(items, function(value, key) {
      if (i < 5) {
        result[key] = value;
      }
      i = i + 1;
    });
    return result;
  };
});

Поменяй 5 на то что хочешь.

fdrv
источник
0

Используйте фильтр limitTo для отображения ограниченного числа результатов в ng-repeat.

<ul class="phones">
      <li ng-repeat="phone in phones | limitTo:5">
        {{phone.name}}
        <p>{{phone.snippet}}</p>
      </li>
</ul>
Раджкиран Шетти
источник
-3

Другой (и мне кажется, лучший) способ добиться этого - фактически перехватить данные. limitTo это хорошо, но что если вы ограничиваетесь 10, когда ваш массив на самом деле содержит тысячи?

При звонке в мой сервис я просто сделал это:

TaskService.getTasks(function(data){
    $scope.tasks = data.slice(0,10);
});

Это ограничивает то, что отправляется в представление, поэтому должно быть намного лучше для производительности, чем делать это во внешнем интерфейсе.

Мэтт Сондерс
источник
Реализация limitTo использует array.slice () в любом случае, любая разница в размере массива должна иметь такую ​​же разницу в производительности, как и при самостоятельном выполнении. github.com/angular/angular.js/blob/master/src/ng/filter/…
rom99
но limitTo на самом деле не ограничивает данные, отправляемые представлению, в то время как делает это таким образом. Я проверил это с помощью console.log ().
Мэтт Сондерс
1
Да, то, что вы делаете, это выставление нового массива представлению (я бы не думал, что он «отправляет» что-либо куда-либо). Если вас интересовали только первые 10 элементов данных, и на данные больше нигде нет ссылок, выполнение этого может уменьшить объем используемой памяти (если предположить, что данные могут собираться мусором). Но если вы все еще сохраняете ссылку на dataоколо, это не более эффективно, чем использование limitTo.
rom99