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.
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:
j'ai dû changer le type de numéro de chaîne...
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
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">
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;
};
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
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= {};
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)">×</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>