2013-10-11 23 views
5

Sembra che debba essere semplice, proprio non riesco a trovare la risposta.angularjs - filtro per più modelli

Diciamo che ho un array di dati, di cui come il seguente:

friends = [{name:'John', age:60, location:'Brighton', street:'Middle Street'}, 
{name:'Bob', age:5, location:'Brighton', street:'High Street'}]; 

Ora, voglio filtrare i dati sulla base di un input di testo in questo modo:

<input ng-model="searchText"> 
<ul> 
    <li ng-repeat="friend in friends | orderBy:'name' | filter:searchText"> 
    {{friend.name}} - {{friend.location}}</li> 
</ul> 

Questo funziona bene ma filtra il testo di input in base a ogni attributo dell'oggetto amico (nome, età, posizione e via). Mi piacerebbe essere in grado di filtrare in base solo al nome e alla posizione (ignorando età e strada). È possibile senza un filtro personalizzato?

risposta

7

Sì, è possibile semplicemente passando un predicato al filtro invece di una stringa:

<li ng-repeat="friend in friends | orderBy:'name' | filter:friendContainsSearchText"> 

$scope.friendContainsSearchText = function(friend) { 
    return friend.name.indexOf($scope.searchText) >= 0 || friend.location.indexOf($scope.searchText) >= 0 
} 
+0

Grazie, funziona bene. L'unica cosa che vale la pena menzionare è che avevo bisogno di convertire il testo in minuscolo e aggiungerlo se (! $ Scope.searchText) restituisce 1; per farlo funzionare. – user2424495

+0

Solo per notare- aggiungendo 'if (! $ Scope.searchText) restituisce 1;' farà sì che restituisca tutti i risultati (nessun filtro) se non viene inserito alcun testo di ricerca. Questo è un aspetto positivo di questo approccio rispetto all'approccio che elenco se ne hai bisogno. – KayakDave

1

In alternativa è possibile utilizzare:

<li ng-repeat="friend in friends | orderBy:'name' | filter:{ name :searchText}">

+0

Questo è probabilmente ciò che desideri, ad eccezione di searchText che ha bisogno di virgolette. filtro: {nome: 'searchText'}. Questo dirà angolare che è una stringa e non un'espressione. – Adam

+1

In realtà @Adam controlla questo violino: http://jsfiddle.net/Dwesk/1/ Non funziona con le virgolette, senza. – KayakDave

+0

Hai assolutamente ragione, volevamo un'espressione in questo caso, ho frainteso la domanda iniziale e la risposta. – Adam

2

Ecco come lo facciamo con un filtro personalizzato.

DEMO: http://plnkr.co/edit/q7tYjOvFjQHSR0QyGETj?p=preview)

[array] | search:query:columns:operator 

> query: this is the term you are looking for 
> columns: an array of the names of the properties you want to look for (if empty, will use the angular filter with query) 
> operator: a boolean to switch between OR (true) and AND (false, default) 

html

<ul> 
    <li ng-repeat="item in list | search:query:['name','location']:operator"> 
    <pre>{{item | json}}</pre> 
    </li> 
</ul> 

js

app.filter('search', function($filter) { 
    return function(input, term, fields, operator) { 
    if (!term) { 
     return input; 
    } 

    fields || (fields = []); 

    if (!fields.length) { 
     return $filter('filter')(input, term); 
    } 

    operator || (operator = false); // true=OR, false=AND 

    var filtered = [], valid; 

    angular.forEach(input, function(value, key) { 
     valid = !operator; 
     for(var i in fields) { 
     var index = value[fields[i]].toLowerCase().indexOf(term.toLowerCase()); 
     // OR : found any? valid 
     if (operator && index >= 0) { 
      valid = true; break; 
     } 
     // AND: not found once? invalid 
     else if (!operator && index < 0) { 
      valid = false; break; 
     } 
     } 
     if (valid) { 
     this.push(value); 
     } 
    }, filtered); 

    return filtered; 
    }; 
}); 
+0

Funziona benissimo! – szymon

-1

È possibile inserire diversi filtri proprio come ....

<div> 
    <input ng-model="Ctrl.firstName" /> 
    <input ng-model="Ctrl.age" /> 

    <li ng-repeat = "employee in Ctrl.employees | filter:{name:Ctrl.firstName} | filter:{age:Ctrl.age}">{{employee.firstName}}</li> 
</div>