AngularJS: получить количество отфильтрованных результатов ng-repeat, чтобы обновить мою разбивку на страницы

Объяснение моего кода:

Ниже представлена ​​простая таблица с ng-repeat, которая перебирает ctrl.persons и сохраняет результаты в переменной ctrl.results. Включен фильтр, который позволяет пользователю искать результаты с помощью ввода текста, а sliceResults — это настраиваемый фильтр для моего Разбиение на страницы Angular-UI (определяет смещение и предел отображаемых результатов на основе текущей страницы разбиения на страницы).

<table>
    <tr ng-repeat="result in ctrl.results = (ctrl.persons | filter:searchKeywords) | sliceResults: ctrl.paginationOffset : ctrl.paginationLimit">
        <td>{{ $index+1 }}</td>
        <td>{{ result.firstName }}</td>
        <td>{{ result.lastName }}</td>
    </tr>
</table>

Results : {{ ctrl.results.length }}

Ситуация:

В конце кода ctrl.results.length возвращает количество результатов в реальном времени и изменяется соответствующим образом, когда пользователь вводит текст для поиска результатов.

Однако, когда количество результатов изменяется, моя нумерация страниц не меняется соответствующим образом и поэтому показывает неправильное количество страниц (например, она все еще может отображать 3 страницы, хотя есть только 1 страница). Количество страниц зависит от переменной в моем контроллере (this.paginationTotalItems).

Вопрос:

Как мне обновить переменную this.paginationTotalItems в моем контроллере, как только количество результатов (ctrl.results.length) изменится в моем представлении? (Или какой альтернативный способ обновить мою разбивку на страницы?)

Что я пробовал:

Я далеко не эксперт по AngularJS, так что не смейтесь надо мной! Я попытался поместить функцию в ng-change со счетчиком результатов, но это не удалось, потому что, по-видимому, для этого требуется ng-model, а я не вижу, чтобы это работало с ng-repeat.

Я также пытался использовать $watch для переменной ctrl.results, но это приводит к серьезной ошибке консоли, поскольку она прерывается после x итераций. Кроме того, я бы предпочел не использовать $watch, потому что я читал, что он работает только с $scope, который я бы предпочел не использовать (я использую синтаксис «контроллер как»).

Заранее спасибо, я приму ответ, который поможет мне решить мою проблему.


person Tom    schedule 16.04.2015    source источник


Ответы (2)


Вы можете использовать $watch с синтаксисом controllerAs в контроллере. Я знаю, ты сказал, что это не твой приоритет, но я думаю, что это может быть твоим лучшим решением. Это будет выглядеть примерно так:

.controller('myCtrl', function () {
    var ctrl = this;
    ...
    $scope.$watch(angular.bind(this, function () {
      return this.results.length;
    }), function (newVal) {
        ctrl.paginationTotalItems = //whatever logic you have
    });
    ....
});

Редактировать: хорошо, я только что подумал о другом способе, которым вам не нужно использовать $scope. Он включает функцию на вашем контроллере и вызывает ее с помощью ng-init, которая будет обновлять вашу переменную (ng-init будет срабатывать каждый раз, когда изменяется повторяющийся список):

Итак, после значительного упрощения ваш контроллер будет выглядеть так:

function MyCtrl() {
    var ctrl = this;
    ctrl.paginationTest = 1;
    ctrl.persons = [1,2,3,4,5];

    ctrl.calcPagination = function () {
        ctrl.paginationTest = Math.floor(Math.random() * 10);
    }
}

И HTML будет:

<table>
          <input ng-model="searchKeywords"/>
        <tr ng-repeat="result in ctrl.results = (ctrl.persons | filter:searchKeywords)" ng-init="ctrl.calcPagination()">

            <td>{{ result }}</td>
            <td>{{ctrl.paginationTest}}</td>
        </tr>
    </table>

Вот Fiddle, взгляните на второй столбец и убедитесь, что он меняется после каждого изменения. во входном элементе. В вашем случае вы просто пересчитаете ctrl.paginationTotalItems.

person Omri Aharon    schedule 16.04.2015
comment
Спасибо за ваш ответ. Да, ваш $watch работает просто отлично! Я, должно быть, как-то испортил свой. Но есть ли способ добиться этого без $watch? У меня нет $scope в моем контроллере (я мог бы добавить его, но не стал бы). - person Tom; 16.04.2015
comment
@Nic На самом деле, может быть ... просто подумал о другом способе, который может вам подойти. Позвольте мне обновить ответ через секунду. - person Omri Aharon; 16.04.2015
comment
@Nic Обновил ответ. - person Omri Aharon; 16.04.2015

Я знаю, что на этот вопрос есть ответ, но я хочу поделиться своим опытом.

У меня были некоторые проблемы с использованием ng-init, предложенного @Omri Aharon, потому что он не вызывал функцию каждый раз, когда я менял значение в текстовом вводе, я решил это, просто удалив ng-init из <tr> и добавив ng-change="ctrl.calcPagination()" к вводу.

HTML-код выглядит так:

<tbody>
  <div class="input-group">
    <span class="input-group-addon glyphicon glyphicon-search" aria-hidden="true"></span>
    <input type="text" class="form-control" placeholder="Filter..." ng-model="ctrl.filterName" ng-change="ctrl.calcPagination()">
  </div>
  <tr ng-repeat="item in ctrl.list | filter: ctrl.filterName | orderBy: ctrl.sortType:ctrl.sortReverse | clientPaginator:ctrl.currentPage:ctrl.itemsPerPage">
    <td>{{item.property}}</td>
  </tr>
</tbody>

И функция в контроллере:

ctrl.calcPagination = function(){
    ctrl.resultCount =  $filter('filter')(ctrl.list, ctrl.filterName).length;
}

Спасибо @Omri Aharon за это простое решение!

person hmartos    schedule 23.07.2015