【问题标题】:Angular pagination not updating when bound list changes due to filtering on an input text box由于对输入文本框进行过滤,当绑定列表发生更改时,角度分页不会更新
【发布时间】:2013-09-11 20:26:49
【问题描述】:

这是场景:

我正在使用带有 Angular JS 和 Boostrap UI 的 ASP.NET MVC 站点。我有一个动态 ul 列表,由通过对 AngularJS 的控制器调用馈送的数据填充,通过输入搜索框对该列表进行过滤。该列表还通过分页(UI Bootstrap 控件)进行控制,我已将其设置为每页显示 100 个左右的项目列表的 10 个结果。当用户在搜索框中输入时,此列表会被过滤,但是我希望分页也能更新,因此请考虑以下示例:

列表有 10 页项目(100 个项目),用户在输入搜索框中键入一些文本,将列表过滤到 20 左右项目,因此分页应从 10 页更新为两页。

我认为某处必须有一个 $watch 设置,可能在过滤后的列表项上,然后更新分页页数,但是我对 AngularJS 很陌生,所以有人可以向我解释一下这是怎么回事完成了吗?

非常感谢。我在下面发布了我的代码:

<div data-ng-app="dealsPage">
<input type="text" data-ng-model="cityName" />
<div data-ng-controller="DestinationController">
    <ul>
        <li data-ng-repeat="deals in destinations | filter: cityName |
            startFrom:currentPage*pageSize | limitTo:pageSize">{{deals.Location}}</li>
    </ul>
    <br />
    <pagination rotate="true" num-pages="noOfPages" current-page="currentPage" 
                max-size="maxSize" class="pagination-small" boundary-links="true"></pagination>
</div>

 var destApp = angular.module('dealsPage', ['ui.bootstrap', 'uiSlider']);
destApp.controller('DestinationController', function ($scope, $http) {
    $scope.destinations = {};
    $scope.currentPage = 1;
    $scope.pageSize = 10;

    $http.get('/Deals/GetDeals').success(function (data) {
        $scope.destinations = data;
        $scope.noOfPages = data.length / 10;
        $scope.maxSize = 5;
    });
});

destApp.filter('startFrom', function () {
    return function (input, start) {
        start = +start; //parse to int
        return input.slice(start);
    };
});

【问题讨论】:

    标签: asp.net-mvc angularjs pagination angularjs-ng-repeat angularjs-bootstrap


    【解决方案1】:

    您好,我尝试使用 Angular Fire 将其与 Firebase 连接起来,它仅在我在搜索输入中键入内容后才有效。在 $scope.$watch 方法中,我使用了 Angular Fire 的 orderByPriorityFilter 将对象转换为数组。

    $scope.$watch('search', function(oldTerm, newTerm) {
      $scope.page = 1;
      // Use orderByPriorityFilter to convert Firebase Object into Array
      $scope.filtered = filterFilter(orderByPriorityFilter($scope.contacts), $scope.search);
      $scope.lastSearch.search = oldTerm;
      $scope.contactsCount = $scope.filtered.length;
    });
    

    初始加载不会加载任何联系人。只有在我开始在输入搜索字段中输入之后。

    【讨论】:

      【解决方案2】:

      jsfiddle 上共享的版本与 ui-bootstrap 0.5.0 兼容,但从 0.6.0 开始发生了重大变化。

      这是一个使用以下库的版本:

      • 角度 1.2.11
      • angular-ui-bootstrap 0.10.0
      • 引导 3.1.0

      这是一个相同的plunker:

      Angular UI Bootstrap Pagination

      【讨论】:

      【解决方案3】:

      因为您的分页是链式过滤器的组合,Angular 不知道当 cityName 更改时,它应该将 currentPage 重置为 1。您需要自己使用自己的 $watch 来处理它。

      您还需要将 startFrom 过滤器调整为 (currentPage - 1) * pageSize,否则,您总是从第 2 页开始。

      一旦你开始这样做,你会注意到你的分页不准确,因为它仍然基于destination.length,而不是经过过滤的目的地子集。为此,您需要将过滤逻辑从视图移动到控制器,如下所示:

      http://jsfiddle.net/jNYfd/

      HTML

      <div data-ng-app="dealsPage">
          <input type="text" data-ng-model="cityName" />
          <div data-ng-controller="DestinationController">
              <ul>
                  <li data-ng-repeat="deals in filteredDestinations | startFrom:(currentPage - 1)*pageSize | limitTo:pageSize">{{deals.Location}}</li>
              </ul>
              <br />
              <pagination rotate="true" num-pages="noOfPages" current-page="currentPage" max-size="maxSize" class="pagination-small" boundary-links="true"></pagination>
          </div>
      

      JavaScript

      var destApp = angular.module('dealsPage', ['ui.bootstrap']);
      
      destApp.controller('DestinationController', function ($scope, $http, $filter) {
          $scope.destinations = [];
          $scope.filteredDestinations = [];
      
          for (var i = 0; i < 1000; i += 1) {
              $scope.destinations.push({
                  Location: 'city ' + (i + 1)
              });
          }
      
          $scope.pageSize = 10;
          $scope.maxSize = 5;
      
          $scope.$watch('cityName', function (newCityName) {
              $scope.currentPage = 1;
              $scope.filteredDestinations = $filter('filter')($scope.destinations, $scope.cityName);
              $scope.noOfPages = $scope.filteredDestinations.length / 10;
          });
      });
      
      destApp.filter('startFrom', function () {
          return function (input, start) {
              start = +start; //parse to int
              return input.slice(start);
          };
      });
      

      【讨论】:

      • 非常感谢!这运作良好。 :) 我所要做的就是将这行代码添加到您的解决方案中:$scope.noOfPages = isNaN($scope.filteredDestinations.length / 10) ? 200 : $scope.filteredDestinations.length / 10; 这样在页面开始时,booststrap UI 分页控件将呈现,否则由于 $scope.noOfPages 变量具有一个“NaN”值。
      • 太棒了,很高兴能帮上忙。欢迎来到 StackOverflow,顺便说一句。如果它回答了您的问题,您应该考虑接受答案。 :)
      • 另外,你能帮我解决一个类似的问题吗,因为我现在被困在这个问题上。我已经将它发布在另一个页面上,这是链接:stackoverflow.com/questions/18722246/… 再次非常感谢。
      猜你喜欢
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2018-05-05
      • 1970-01-01
      相关资源
      最近更新 更多