web-dev-qa-db-fra.com

AngularJS: compter les éléments filtrés

Je montre des sous-ensembles d'une liste si une case est cochée. Je voudrais remplacer le X à côté de la case à cocher par le nombre de la liste correspondant aux critères de sélection. J'ai un plongeur qui fait tout mais compte le sous-ensemble ici .

Mon contrôleur ressemble à ceci:

var app = angular.module('app', []);

app.controller('MainController', function($scope){
  $scope.cbMarvel = true;
  $scope.cbDCComics = true;

  $scope.heroes = [
    {
      id: 1,
      name: 'Iron Man',
      fname: 'Tony',
      lname: 'Stark',
      location: 'Stark Tower',
      comic: 'Marvel'
    },
    {
      id: 2,
      name: 'Batman',
      fname: 'Bruce',
      lname: 'Wayne',
      location: 'Bat Cave',
      comic: 'DC'
    },
    {
      id: 3,
      name: 'Superman',
      fname: 'Clark',
      lname: 'Kent',
      location: 'Metroplis',
      comic: 'DC'
    },
    {
      id: 1,
      name: 'Daredevil',
      fname: 'Jack',
      lname: 'Murdock',
      location: 'Court Room',
      comic: 'Marvel'
    },
    {
      id: 5,
      name: 'Flash',
      fname: 'Barry',
      lname: 'Allen',
      location: 'Speedline',
      comic: 'DC'
    },
    {
      id: 6,
      name: 'Hulk',
      fname: 'Bruce',
      lname: 'Banner',
      location: 'Labratory',
      comic: 'Marvel'
    },
    {
      id: 7,
      name: 'Hawkeye',
      fname: 'Clint',
      lname: 'Barton',
      location: 'Nest',
      comic: 'Marvel'
    },
    {
      id: 8,
      name: 'Thor',
      fname: 'Donald',
      lname: 'Blake',
      location: 'Asgard',
      comic: 'Marvel'
    }
  ];
});

Et ma vue ressemble à ceci:

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <link data-require="bootstrap@*" data-semver="3.2.0" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css" />
    <link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
    <script data-require="bootstrap@*" data-semver="3.2.0" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>
    <script data-require="[email protected] current" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="[email protected]" data-semver="1.2.20" src="https://code.angularjs.org/1.2.20/angular.js"></script>
    <script data-require="angular-ui-bootstrap@*" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="MainController">
     <fieldset>
        <legend>Comments Log</legend>
        <div class="row">
            <div class="col-md-4">
                <input type="checkbox" ng-model="cbMarvel"/> Marvel [X]
            </div>
            <div class="col-md-4">&nbsp;</div>
            <div class="col-md-4">
                <input type="checkbox" ng-model="cbDCComics"/> DC Comics [X]
            </div>
        </div>

        <div class="row">&nbsp;</div>

        <div class="row col-md-10">
            <div ng-if="heroes.length == 0"><b>No Heroes Found!</b>
            </div>
            <div ng-repeat="h in heroes | filter:{comic:'Marvel'}" ng-show="cbMarvel">
                {{ h.name}} - {{h.comic}}
            </div>
            <div ng-repeat="h in heroes | filter:{comic:'DC'}" ng-show="cbDCComics">
              {{ h.name}} - {{h.comic}}
            </div>
        </div>
    </fieldset>
  </body>

</html>
16
jgravois

Vous pouvez définir ce nombre dans le modèle de vue lui-même lors de la liaison des données ou simplement avoir une méthode sur la portée qui renvoie le nombre.

app.controller('MainController', function($scope, filterFilter){
   ....
    $scope.getCount = function(strCat){
      return filterFilter( $scope.heroes, {comic:strCat}).length;
    }
    ...
});

et l'utiliser comme: -

  Marvel [{{getCount("Marvel")}}]
  .....
  DC Comics [{{getCount("DC")}}]

Plnkr

Si la liste ne change pas lorsque vous êtes sur la page, je suggère de découvrir la longueur et de la lier à une propriété dans le modèle de vue lui-même, et de l'utiliser dans la vue.

 //Set your data model
  $scope.cbMarvel = {value:true, count:getCount('Marvel')};
  $scope.cbDCComics = {value:true, count:getCount('DC')};

et à votre avis

   <input type="checkbox" ng-model="cbMarvel.value"/> Marvel [{{cbMarvel.count}}]

Plnkr2

Si votre jeu de données est énorme, au lieu d'utiliser un filtre à l'intérieur du getCount, utilisez un forEach et remplissez le nombre pour chaque type à la fois.


En fait, vous n'avez pas du tout besoin d'un filtre, il semble inefficace de parcourir la même liste en utilisant un filtre dans votre cas. La vôtre est une liste statique, alors catégorisez-la dans le contrôleur lui-même.

var comics = $scope.comics  = {}; //Dictionary of comics
  //Create the collection here.
  angular.forEach(heroes, function(itm){
    if(!comics[itm.comic]){
     comics[itm.comic] = {name:itm.comic, value:true, count:1, items:[itm] };
     return;
    }

    comics[itm.comic].count++; //Incr count
    comics[itm.comic].items.Push(itm); //Push specific item
  });

et supprimez tous les filtres dans votre vue et faites: -

    <div ng-repeat="h in comics.Marvel.items" ng-show="comics.Marvel.value">
        {{ h.name}} - {{h.comic}}
    </div>
    <div ng-repeat="h in comics.DC.items" ng-show="comics.DC.value">
      {{ h.name}} - {{h.comic}}
    </div>

Plnk3 - le meilleur

15
PSL

En supposant que votre liste de personnes est dans une variable de données et que vous filtrez les personnes à l'aide du modèle de requête, le code suivant fonctionnera pour vous:

  • Nombre de personnes visibles: {{(data|filter:query).length}}
  • Nombre total de personnes: {{data.length}}

résumé

{{data.length}} - imprime le nombre total de personnes

{{(data|filter:query).length}} - imprime le nombre filtré de personnes

22
Sajjad Ali Khan

Solution possible 1: Inline

Vous pouvez en fait enregistrer une référence aux résultats filtrés dans une variable: h in filtered.marvel = (heroes | filter:{comic:'Marvel'}), que vous pouvez utiliser comme ceci: filtered.marvel.length.

Voir: Plunkr

Solution possible 2: dans le contrôleur

Vous pouvez également déplacer ce code vers votre contrôleur:

$scope.filteredHeroes.marvel = $filter('filter')($scope.heroes, {comic:'Marvel'});

, que vous pourriez utiliser par ng-repeat="hero in filteredHeroes.marvel"

et {{filteredHeroes.marvel.length}}

(N'oubliez pas d'ajouter $ filter comme dépendance du contrôleur)

Voir: Plunkr

12
user125661

Pour trouver les objets de comptage, j'utilise <scope_obj>.length dans le .html modèle.

Voici mon contrôleur:

conciergeControllers.controller('GuestMsgPreviewCtrl', ['$scope', 'GuestMessages',
    function($scope, GuestMessages) {
    $scope.guests = GuestMessages.query();
}]);

Et le modèle (chaque objet invité a un attribut messages qui est un objet tableau, donc .length renvoie le nombre d'objets message imbriqués:

<ul ng-repeat="guest in guests">
  <li>[[ guest.messages.length ]]</li>
</ul>
0
Aaron Lelevier