web-dev-qa-db-fra.com

Filtre de case à cocher AngularJS

Je voudrais filtrer les résultats.

Il y a une liste de vins, mon souhait est quand aucune case n'est cochée, la liste entière des vins est affichée.

  • lorsqu'une seule case est cochée, la catégorie associée s'affiche
  • lorsque plusieurs cases sont cochées, les catégories associées s'affichent

Je suis un débutant à AngularJS, j'ai essayé avec ng-model sans succès, voici le code sans ng-model associé à la fonction:

<html ng-app="exampleApp">
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.10/angular.min.js"></script>

    <script>
        angular.module("exampleApp", [])
                .controller("defaultCtrl", function ($scope) {
                    $scope.wines = [
                        { name: "Wine A", category: "red" },
                        { name: "Wine B", category: "red" },
                        { name: "wine C", category: "white" },
                        { name: "Wine D", category: "red" },
                        { name: "Wine E", category: "red" },
                        { name: "wine F", category: "white" },
                        { name: "wine G", category: "champagne"},
                        { name: "wine H", category: "champagne" }

                    ];


                    $scope.selectItems = function (item) {
                        return item.category == "red";
                    };

                    $scope.selectItems = function (item) {
                        return item.category == "white";
                    };

                    $scope.selectItems = function (item) {
                        return item.category == "champagne";
                    };
                });
    </script>
</head>
<body ng-controller="defaultCtrl">

<h4>red: <input type="checkbox"></h4>
<h4>white: <input type="checkbox"></h4>
<h4>champagne: <input type="checkbox"></h4>



            <div ng-repeat="w in wines | filter:selectItems">
                {{w.name}}
                {{w.category}}
            </div>


</body>
</html>

Comment utiliser ng-model ou ng-change pour associer une fonction à chaque bouton de case à cocher pour avoir un modèle de filtrage en temps réel ??

18
Stéphane

Je préfère utiliser filter comme $filter

app.filter('someFilter',checkboxFilter)
checkboxFilter() {
    return function (arr,filter,key,noOne=false) {
        // arr is an array of objects
        // filter is checkbox filter. someting like {1:true,2:false}
        // key is a property in ech object inside arr
        // noOne is a behavior if none of checkbox is activated (default:false)
        if (!arr.length) return null;

        function noOneCheck(filter) {
            return Object.keys(filter).every((key) => {
                return !filter[key]
            })
        }
        return arr.filter((i) => {
            return filter[i[key]] || (noOne && noOneCheck(filter))
        })
    }
};

html:

ng-repeat="u in project.projectTeamInvite | checkbox:project.status:'status' track by $index">
1
dimson d

Il existe plusieurs implémentations possibles. En voici un:

  1. Avoir un objet $scope.filter = {} Pour conserver l'état de chaque filtre. Par exemple. {red: true, white: false...}.

  2. Associez chaque case à cocher à la propriété correspondante à l'aide de ng-model. Par exemple: input type="checkbox" ng-model="filter['red']" />.

  3. Avoir une fonction (par exemple $scope.filterByCategory(wine)) qui décide si un vin doit être affiché ou non (basé sur l'objet $scope.filter).

  4. Utilisez cette fonction pour filtrer les éléments en fonction de leur catégorie. Par exemple. <div ng-repeat="wine in wines | filter:filterByCategory">


La fonction filterByCategory pourrait être implémentée comme ceci:

function filterByCategory(wine) {
  // Display the wine if
  var displayWine =
      // the wine's category checkbox is checked (`filter[category]` is true)
      $scope.filter[wine.category] ||   // or 

      // no checkbox is checked (all `filter[...]` are false)
      noFilter($scope.filter);

  return displayWine;
};

noFilter() est une fonction qui vérifie si un filtre est activé (et renvoie true s'il n'y en a pas):

function noFilter(filterObj) {
  return Object.
    keys(filterObj).
    every(function (key) { return !filterObj[key]; });
}

Voir aussi ceci courte démo.


[~ # ~] mise à jour [~ # ~] :

J'ai créé une version modifiée, qui prend en charge plusieurs filtres (pas seulement le filtrage par catégorie).
Fondamentalement, il détecte dynamiquement les propriétés disponibles (en fonction du premier élément wine), ajoute des contrôles (groupes de cases à cocher) pour appliquer des filtres en fonction de chaque propriété et propose une fonction de filtre personnalisée qui :

  1. Filtre chaque élément wine, en fonction de chaque propriété.
  2. Si une propriété n'a pas de filtre appliqué (c'est-à-dire qu'aucune case n'est cochée), elle est ignorée.
  3. Si une propriété a des cases à cocher cochées, elle est utilisée pour filtrer les éléments wine (voir ci-dessus).
  4. Il existe un code pour appliquer plusieurs filtres à l'aide de AND (c'est-à-dire que toutes les propriétés doivent correspondre) ou OR (au moins une propriété doit correspondre).

Voir aussi ceci démo mise à jour.

46
gkalpak