AngularJS:获取过滤后的 ng-repeat 结果计数以更新我的分页

AngularJS: get filtered ng-repeat result count to update my pagination

我的代码解释:

下面是一个简单的 table,其中有一个 ng-repeat 循环遍历 ctrl.persons,并将结果存储在变量 ctrl.results 中。包含一个过滤器,允许用户使用文本输入搜索结果,sliceResults 是我的 Angular-UI pagination 的自定义过滤器(它根据当前设置确定要显示的结果的偏移量和限制分页的页面)。

<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 returns 实时结果的数量,并在用户填写文本输入以搜索结果时相应地发生变化。

然而,当结果数量发生变化时,我的分页并没有相应改变,因此显示的页数不正确(例如,它仍然可以显示 3 页,而只有 1 页)。页数基于我的控制器中的一个变量 (this.paginationTotalItems)。

问题:

如何在我的视图中的结果数量 (ctrl.results.length) 发生变化时立即更新控制器中的变量 this.paginationTotalItems? (或者,有什么替代方法可以更新我的分页?)

我试过的:

我远不是AngularJS专家,大家不要笑话我!我试图在 ng-change 中放置一个带有结果计数的函数,但失败了,因为显然它需要 ng-model 而我没有看到它与 ng-repeat.

一起工作

我还尝试在 ctrl.results 变量上使用 $watch,但这导致了一个巨大的控制台错误,因为它在 x 次迭代后中止。另外,我宁愿不使用 $watch,因为我读到它只适用于 $scope,我宁愿不使用它(我使用 "controller as" 语法)。

在此先感谢,我会接受有助于我解决问题的答案。

您可以在控制器中使用带有 controllerAs 语法的 $watch。我知道你说过这不是你的首要任务,但我认为这可能是你最好的解决方案。它看起来像这样:

.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.

我知道这个问题已经得到解答,但我想分享我的经验。

我在使用@Omri Aharon 提出的 ng-init 时遇到了一些问题,因为每次我更改文本输入中的值时它都没有调用函数,我解决了它只是删除 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 提供这个简单的解决方案!