Cómo filtrar por propiedad de objeto en angularJS

139

Estoy tratando de crear un filtro personalizado en AngularJS que filtre una lista de objetos por los valores de una propiedad específica. En este caso, quiero filtrar por la propiedad "polaridad" (valores posibles de "Positivo", "Neutral", "Negativo").

Aquí está mi código de trabajo sin el filtro:

HTML:

<div class="total">
    <h2 id="totalTitle"></h2>
    <div>{{tweets.length}}</div>
    <div id="totalPos">{{tweets.length|posFilter}}</div>
    <div id="totalNeut">{{tweets.length|neutFilter}}</div>
    <div id="totalNeg">{{tweets.length|negFilter}}</div>
</div>

Aquí está la matriz "$ scope.tweets" en formato JSON:

{{created_at: "Date", text: "tweet text", user:{name: "user name", screen_name: "user       screen name", profile_image_url: "profile pic"}, retweet_count: "retweet count", polarity: "Positive"},
 {created_at: "Date", text: "tweet text", user:{name: "user name", screen_name: "user screen name", profile_image_url: "profile pic"}, retweet_count: "retweet count", polarity: "Positive"},
 {created_at: "Date", text: "tweet text", user:{name: "user name", screen_name: "user screen name", profile_image_url: "profile pic"}, retweet_count: "retweet count", polarity: "Positive"}}

El mejor filtro que pude encontrar de la siguiente manera:

myAppModule.filter('posFilter', function(){
return function(tweets){
    var polarity;
    var posFilterArray = [];
    angular.forEach(tweets, function(tweet){
        polarity = tweet.polarity;
        console.log(polarity);
        if(polarity==='Positive'){
              posFilterArray.push(tweet);
        }
        //console.log(polarity);
    });
    return posFilterArray;
};
});

Este método devuelve una matriz vacía. Y nada se imprime desde la declaración "console.log (polaridad)". Parece que no estoy insertando los parámetros correctos para acceder a la propiedad del objeto de "polaridad".

¿Algunas ideas? Su respuesta es muy apreciada.

sh3nan1gans
fuente
3
Buena pregunta, pero el código podría reducirse, gran parte de él no es relevante para la pregunta.
setec

Respuestas:

218

Simplemente tiene que usar el filterfiltro (consulte la documentación ):

<div id="totalPos">{{(tweets | filter:{polarity:'Positive'}).length}}</div>
<div id="totalNeut">{{(tweets | filter:{polarity:'Neutral'}).length}}</div>
<div id="totalNeg">{{(tweets | filter:{polarity:'Negative'}).length}}</div>

Fiddle

Agujero negro
fuente
1
¿Hay alguna manera de filtrar la lista de elementos pasando un filtro personalizado a un evento ng-click fuera de la declaración ng-repeat? En este caso, quiero colocar tres botones de "polaridad" sobre los resultados que se filtran según la clasificación.
sh3nan1gans
2
No estoy seguro de entenderlo. Si desea elegir la polaridad para filtrar, puede pasar una variable de alcance en lugar de un texto sin formato: filter:{polarity:polarityToFilter}donde $scope.polarityToFilterse rellena haciendo clic en uno de los tres botones. Es esto lo que estas tratando de hacer ?
Blackhole
Parece que podría funcionar. Sin embargo, mi aplicación también necesita poder eliminar elementos de lista individuales.
sh3nan1gans
El problema con el filtrado es que se crea una nueva matriz cada vez que se aplica un filtro que rompe el vínculo entre un elemento filtrado y su índice original en la matriz no filtrada. ¿Hay alguna manera de mantener el empate o es ng-hide mi única opción? Aquí hay un tutorial para una alternativa al filtrado usando ng-hide: bennadel.com/blog/…
sh3nan1gans
ngRepeat expone una $indexpropiedad en el ámbito local que también puede usar.
Blackhole
27

La documentación tiene la respuesta completa. De todos modos, así es como se hace:

<input type="text" ng-model="filterValue">
<li ng-repeat="i in data | filter:{age:filterValue}:true"> {{i | json }}</li>

filtrará solo ageen la datamatriz y truees para la coincidencia exacta.

Para un filtrado profundo,

<li ng-repeat="i in data | filter:{$:filterValue}:true"> {{i}}</li>

El $es una propiedad especial para el filtro profundo y truees para la coincidencia exacta como arriba.

Abel Terefe
fuente
Simple y limpio.
scaryguy
¿Este filtro está incorporado o necesita ser escrito en Angular y AngularJS?
P Satish Patro
23

También podría hacer esto para hacerlo más dinámico.

<input name="filterByPolarity" data-ng-model="text.polarity"/>

Entonces ng-repeat se verá así

<div class="tweet" data-ng-repeat="tweet in tweets | filter:text"></div>

Por supuesto, este filtro solo se usará para filtrar por polaridad

Llewellyn Collins
fuente
5

Tenemos colección de la siguiente manera:


ingrese la descripción de la imagen aquí

Sintaxis:

{{(Collection/array/list | filter:{Value : (object value)})[0].KeyName}}

Ejemplo:

{{(Collectionstatus | filter:{Value:dt.Status})[0].KeyName}}

-O-

Sintaxis:

ng-bind="(input | filter)"

Ejemplo:

ng-bind="(Collectionstatus | filter:{Value:dt.Status})[0].KeyName"
Rahul Modi
fuente
4

Puedes probar esto. está funcionando para mí 'nombre' es una propiedad en arr.

repeat="item in (tagWordOptions | filter:{ name: $select.search } ) track by $index
Satish Singh
fuente