Filtre strict AngularJS sur un seul champ

j'ai un formulaire avec plusieurs filtres, mais pour certains, j'ai besoin d'une stricte comparaison.

tl;dr: comparaison stricte pour user_id pas firstname.

<select ng-model="search.user_id">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="10">10</option>
    <option value="11">11</option>
    <option value="23">23</option>
</select>

<input type="text" ng-model="search.firstname">

<ul>
    <li ng-repeat="user in users | filter:search">#{{ user.user_id }} {{ user.firstname}}</li>
</ul>

j'ai essayé le troisième paramètre true mais cela fonctionne aussi pour firstname filtre.

Le problème est: si vous sélectionnez la valeur 2, tous les utilisateurs avec un 2 dans leur id sera filtré, Je ne veux pas de ce comportement.

Ici tripoter.

12
demandé sur Syl 2014-07-21 18:37:29

6 réponses

j'ai essayé de le corriger nativement, plutôt qu'avec des filtres personnalisés, son fonctionnement, voici le PLUNKER LINK

devait spécifier plusieurs filtres étiquette

<li ng-repeat="user in users | filter:{'user_id':  search.user_id}: true | filter: {'firstname' : search.firstname}">

bien qu'il y ait peu de mises en garde:

  1. j'ai dû changer le type de numéro de chaîne...

  2. si je réinitialise la valeur de correspondance exacte cela ne fonctionne pas...

alors j'ai dû écrire une coutume filer qui fonctionne pour une correspondance exacte et ignore vide/valeurs null

$scope.filter2 = function(field1, field2) {
  if(field2 === "" || field2 === null) return true;
  return field1 === field2;
};

vous trouver tous les deux dans la plunker lien

15
répondu harishr 2014-07-21 16:16:59

vous pouvez avoir une fonction comme celle-ci dans votre controller

$scope.identical = function(actual, expected){
    return actual === parseInt(expected);
}

et puis vous pouvez l'utiliser comme ceci

<li ng-repeat="user in users | filter:search.user_id:identical">
1
répondu Edminsson 2014-07-21 15:20:01

J'ai utilisé la solution de HarisR mais je l'ai modifiée pour qu'elle puisse être utilisée avec des nombres aussi si vous avez besoin de votre valeur en tant que nombre.

$scope.filter2 = function(field1, field2) {
  if(field2 === "" || field2 === null) return true;
  return field1.toString() === field2;
};

ou

$scope.filter2 = function(field1, field2) {
  if(field2 === "" || field2 === null) return true;
  return ""+field1 === field2;
};
1
répondu Stefan Dragicevic 2014-10-09 06:55:30

j'ai rencontré ce problème lorsque j'ai chargé une configuration de formulaire à partir de Json et que les nombres ont été passés en inn Comme nombre et non String.

<div ng-repeat="selectedComponent from ctrl.drivers.components |
     filter:{
             manufacturer: component.manufacturer, 
             type: component.type}:true">

quand j'avais un type de composant de 1 et 10 les deux apparaîtraient dans mon ng-repeat avant que j'ajoute le :true à mon filtre, et rien quand j'ai ajouté l'égalité stricte.

pour corriger ceci j'ai ajouté une méthode à mon controller appelée castToInt

ctrl.castToInt = function(value){
    return parseInt(value);
};

Puis j'ai modifié mon filtre pour afficher

<div ng-repeat="selectedComponent from ctrl.drivers.components |
     filter:{
             manufacturer: component.manufacturer, 
             type: ctrl.castToInt(component.type)}:true">

Voila alors tout a fonctionné

a mon avis, c'est :true fait respecter l'égalité stricte === ainsi vous obtiendrez un faux si vous comparez les différents types.

si vous pouvez accepter de changer le type de votre valeur alors la réponse acceptée est suffisante, mais si vous n'avez aucun contrôle sur les données qui vous sont présentées cette méthode fonctionne.

-- Thomas

1
répondu tFlolo 2015-12-04 14:02:16

Changement dans votre code html:

<li ng-repeat="user in users | filter:f">#{{ user.user_id }} {{ user.firstname}}</li>

je suppose que vous voulez and si les deux valeurs sont présents. La changer en une or si vous en avez besoin. Filtre personnalisé fonction:

$scope.f = function(val) {
    var hasUserId = $scope.search.user_id;
    var hasName = $scope.search.firstname;

    var firstNameMatch = function() { return val.firstname.indexOf($scope.search.firstname) > -1 };
    var userIdMatch = function() { return $scope.search.user_id == val.user_id };

    if(hasUserId && hasName) {
       return  firstNameMatch() && userIdMatch()
    } else if (hasUserId) {
        return userIdMatch();
    } else if (hasName) {
        return firstNameMatch();
    }
    return true;
};

un changement de plus à votre controller:

$scope.search= {};

Violon Fourchu.

0
répondu Andy Gaskell 2014-07-21 15:33:24

si vous voulez rechercher par nom par exemple, il suffit d'ajouter une zone de texte avec nom= Recherche.votre nom de champ, si vous voulez rechercher dans tous les champs, il vous suffit de créer une zone de texte avec recherche.$ et puis il suffit d'ajouter le filtre:recherche:la stricte sur votre ng-repeat directive.

exemple de Code pour mieux expliquer:

<div class="customers view">
<div class="container">
    <header>
        <h3>Customers</h3>
    </header>
    <div class="row">
        <div class="span3">
            Search All:
            <input data-ng-model="search.$" type="text" placeholder="All Search" />
        </div>
        <div class="span3">
            Search By Name: 
            <input data-ng-model="search.firstName" type="text" placeholder="First Name Search" />
        </div>
        <div class="span3">
            Search By LastName:
            <input data-ng-model="search.lastName" type="text" placeholder="Last Name Search" />                
        </div>
        <div class="span3">
            Search By City:
            <input data-ng-model="search.city" type="text" placeholder="City Search" />
        </div>

    </div>
    <div>
        <div class="row cardContainer">
            <div class="span3 card" data-ng-repeat="customer in customers | filter:search:strict | orderBy:'firstName'">
                <button class="btn close cardClose" data-ng-click="deleteCustomer(customer.id)">&times;</button>
                <div class="cardHeader">{{customer.firstName + ' ' + customer.lastName}}</div>
                <div class="cardBody">{{customer.city}}</div>
                <a href="#/customerorders/{{customer.id}}" class="cardBody btn-link">View {{ customer.orders.length }} Orders</a>
            </div>
        </div>
    </div>
</div>

0
répondu Leandro Nascimento Dias 2017-04-14 21:59:59