Angular pagination not updating when bound list changes due to filtering on an input text box

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-03 13:33:16

问题


Here's the scenario:

I am using an ASP.NET MVC site with Angular JS and Boostrap UI. I have a dynamic ul list populated by data fed through a controller call to AngularJS, filtering on that list through an input search box. The list is also controlled through pagination (UI Bootstrap control) that I've setup to show 10 results per page for the list of 100 or so items. This list is filtered as the user types in the search box, however I would like the pagination to update as well so consider the following example:

The list has 10 pages of items (100 items), the user types some text in the input search box which filters the list down to 20 or so items, so the pagination should be updated from 10 pages to two pages.

I figure there must be a $watch setup somewhere, perhaps on the list items after it has been filtered and then update the pagination page count, however I'm pretty new to AngularJS so can someone please explain to me how this could be done?

Thanks very much. I have posted my code below:

<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);
    };
});

回答1:


Because your pagination is a combination of chained filters, Angular has no idea that when cityName changes, it should reset currentPage to 1. You'll need to handle that yourself with your own $watch.

You'll also want to adjust your startFrom filter to say (currentPage - 1) * pageSize, otherwise, you always start at page 2.

Once you get that going, you'll notice that your pagination is not accurate, because it's still based on destination.length, and not the filtered sub-set of destinations. For that, you're going to need to move your filtering logic from your view to your controller like so:

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);
    };
});



回答2:


The version shared on jsfiddle is compatible with ui-bootstrap 0.5.0 but from 0.6.0 onwards there have been breaking changes.

Here is a version that uses the following libraries:

  • angular 1.2.11
  • angular-ui-bootstrap 0.10.0
  • bootstrap 3.1.0

Here is a plunker for the same:

Angular UI Bootstrap Pagination




回答3:


Hello I tried to hook this up with Firebase using Angular Fire and it only works after I type something in the search input. In the $scope.$watch method, I used Angular Fire's orderByPriorityFilter to convert the object to an array.

$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;
});

Initial load doesn't load any contacts. It's only after I start typing in the input search field.



来源:https://stackoverflow.com/questions/18679765/angular-pagination-not-updating-when-bound-list-changes-due-to-filtering-on-an-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!