web-dev-qa-db-fra.com

Mettre à jour la pagination dans AngularJS après le filtrage

J'ai déjà implémenté la pagination. Maintenant, je veux que la pagination soit mise à jour après avoir filtré mes résultats.

La forme:

<input type="text" data-ng-model="search.name" data-ng-change="filter()"/>

La liste:

<li data-ng-repeat="data in filtered = (list | filter:search) | filter:search | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">{{data.name}}</li>

La pagination:

<pagination data-boundary-links="true" data-num-pages="noOfPages" data-current-page="currentPage" max-size="maxSize"></pagination>

Le controlle:

$scope.filter = function() {
    window.setTimeout(function() { //wait for 'filtered' to be changed
        $scope.noOfPages = Math.ceil($scope.filtered.length/$scope.entryLimit);
        $scope.setPage = function(pageNo) {
            $scope.currentPage = pageNo;
        };
    }, 10);
};

Mon problème est que la pagination est juste mise à jour après avoir cliqué sur un numéro de page ou après avoir entré le caractère suivant dans le champ de saisie. Il s'agit donc de mettre à jour une étape trop tard.

[~ # ~] modifier [~ # ~] : j'ai ajouté la source à jsFiddle: http://jsfiddle.net/eqCWL/2 /

34
StinsonMaster

Utilisation $timeout au lieu de window.setTimeOut. $timeout est correctement enveloppé pour fonctionner de manière cohérente dans Angular.

3
abject_error

@abject_error's answer using $timeout fonctionne. J'ai édité votre violon avec sa suggestion et l'ai fait jsFiddle

[~ # ~] mise en garde [~ # ~]

Je pense que la solution indique un problème plus important sous la forme d'une condition de concurrence!

jsFiddle utilisant filterFilter et $ watch

et ce violon est le chemin pour les vrais.

Et voici l'explication

Votre condition de concurrence entre la gestion du changement de search et la disponibilité de $scope.filtered.

Je pense que les coupables à éliminer pour résoudre cette condition de concurrence sont:

ng-model="search" ng-change="filter()"

et

ng-repeat="data in filtered = (list | filter:search)......."

En utilisant ng-change pour déclencher "filter ()" pour faire le calcul de noOfPages mais aussi en fonction d'un changement de recherche afin de créer filtered. En procédant de cette façon, vous vous assurez que la liste filtrée ne peut pas être prête à temps pour calculer le nombre de pages, et c'est pourquoi entravant "filter ()" de 10 ms avec un délai d'attente vous donne l'illusion d'un programme de travail.

Ce dont vous avez besoin est un moyen de "surveiller" search les modifications, puis de filtrer la liste à un endroit où vous avez accès à la fois à la création de $scope.filtered et calcul $scope.noOfPages. Tout en séquence, sans course.

Angular a cette façon! Il est possible d'utiliser le filtre filter dans votre contrôleur comme fonction très mal nommée: filterFilter. Vérifiez cela dans le Guide des filtres - Utilisation de filtres dans les contrôleurs et les services

Injectez-le dans le contrôleur.

function pageCtrl($scope, filterFilter) {
    // ...
}

Utilisez-le dans un $watch fonction, documentée dans les scopes docs

$scope.$watch('search', function(term) {  
    // Create filtered 
    $scope.filtered = filterFilter($scope.list, term);  

    // Then calculate noOfPages
    $scope.noOfPages = Math.ceil($scope.filtered.length/$scope.entryLimit);  
})

Modifiez le modèle pour refléter notre nouvelle façon. Plus de filtre DOM, ou ng-change

<input type="text" ng-model="search" placeholder="Search"/>

et

<li ng-repeat="data in filtered | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
    {{data.name}}
</li>
36
nackjicholson

Vous pouvez simplement utiliser cette directive à la place:

https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination

Il offre une pagination avec un filtre tout en gardant le code Nice et propre.

Félicitations à Michaelbromley pour le grand code.

4
peppydip

Utilisez angular $scope.$watch

$scope.$watch('search', function(term) {
    $scope.filter = function() {
        $scope.noOfPages = Math.ceil($scope.filtered.length/$scope.entryLimit);
    }
});

La source ; http://jsfiddle.net/eqCWL/2/

Démo; http://jsfiddle.net/eqCWL/192/

2
sinHoot