¿Cómo filtro una matriz con AngularJS y uso una propiedad del objeto filtrado como el atributo ng-model?

122

Si tengo una matriz de objetos y quiero vincular el modelo angular a una propiedad de uno de los elementos basada en un filtro, ¿cómo hago eso? Puedo explicar mejor con un ejemplo concreto:

HTML:

<!DOCTYPE html>
<html ng-app>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
        <meta charset=utf-8 />
        <title>JS Bin</title>
    </head>
    <body ng-controller="MyCtrl">
        <input ng-model="results.year">
        <input ng-model="results.subjects.title | filter:{grade:'C'}">
    </body>
</html>

Controlador:

function MyCtrl($scope) {
  $scope.results = {
    year:2013,
    subjects:[
      {title:'English',grade:'A'},
      {title:'Maths',grade:'A'},
      {title:'Science',grade:'B'},
      {title:'Geography',grade:'C'}
    ]
  };
}

JSBin: http://jsbin.com/adisax/1/edit

Quiero filtrar la segunda entrada a la asignatura con una calificación 'C', pero no quiero vincular el modelo a la calificación ; Quiero vincularlo con el título de la asignatura que tiene el grado 'C'.

¿Es esto posible y, de ser así, cómo se hace?

Bernhard Hofmann
fuente

Respuestas:

127
<div ng-repeat="subject in results.subjects | filter:{grade:'C'}">
    <input ng-model="subject.title" />
</div>
JB Nizet
fuente
1
Veo a dónde vas con eso, pero realmente no quería un repetidor. La propiedad por la que realmente filtraré es una columna de identidad, por lo que es única. Pero veo que esta sería la forma correcta de resolver el problema genérico.
Bernhard Hofmann
1
Este es un tutorial para los italianos :) dev.stasbranger.com/post/77190983049/…
Silvio Troia
10
esto fue muy útil, y para el inverso (todo lo que no sea C), esto funcionaría:filter:{grade:'!'+'C'}
pulkitsinghal
2
¿Puedes hacer lo mismo con un grade array? En mi caso, construyo mi matriz de calificaciones desde una vista de árbol y quiero filtrar el resultado para aquellos en la matriz.
Juan Carlos Oropeza
157

Puede usar el filtro "filtro" en su controlador para obtener todas las calificaciones "C". Obtener el primer elemento de la matriz de resultados le dará el título de la asignatura que tiene la calificación "C".

$scope.gradeC = $filter('filter')($scope.results.subjects, {grade: 'C'})[0];

http://jsbin.com/ewitun/1/edit

Lo mismo con el simple ES6:

$scope.gradeC = $scope.results.subjects.filter((subject) => subject.grade === 'C')[0]
Oliver
fuente
lo siento, no estoy siguiendo ese segundo filtro ('filtro') ¿me puede explicar un poco más?
Winnemucca
1
@stevek Ese es el nombre del filtro. El método filter () te da el filtro. Es solo que ese filtro se llama filtro porque filtra una matriz. Se vería así con el filtro de moneda: $ filter ('moneda') (cantidad, símbolo, fracción Tamaño
Oliver
61

Aquí hay un JSBin modificado con una muestra de trabajo:

http://jsbin.com/sezamuja/1/edit

Esto es lo que hice con los filtros en la entrada:

<input ng-model="(results.subjects | filter:{grade:'C'})[0].title">
lukeatdesignworks
fuente
1
Este es el verdadero negocio. Este es el poder. Esta es la forma. Fui con esto y ahora estoy feliz.
user1576978
13

tenga en cuenta que si usa $ filter así:

$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});

y tuviste otra calificación para, Oh no sé, CC o AC o C + o CCC que los atrae. debe agregar un requisito para una coincidencia exacta:

$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'}, true);

Esto realmente me mató cuando obtuve algunos detalles de comisiones como este:

var obj = this.$filter('filter')(this.CommissionTypes, { commission_type_id: 6}))[0];

solo me llamaron por un error porque estaba introduciendo el ID de comisión 56 en lugar de 6.

Agregar las verdaderas fuerzas una coincidencia exacta.

var obj = this.$filter('filter')(this.CommissionTypes, { commission_type_id: 6}, true))[0];

Aún así, prefiero esto (uso el mecanografiado, de ahí el "Let" y =>):

let obj = this.$filter('filter')(this.CommissionTypes, (item) =>{ 
             return item.commission_type_id === 6;
           })[0];

Lo hago porque, en algún momento en el camino, es posible que desee obtener más información de los datos filtrados, etc., tener la función justo allí deja el capó abierto.

Daniel Morris
fuente
Tuve el mismo error que tú, gracias por la pista con el tercer parámetro booleano. No lo sabía.
Georg Leber
12

Si desea crear una lista separada de resultados en el controlador, puede aplicar un filtro

function MyCtrl($scope, filterFilter) {
  $scope.results = {
    year:2013,
    subjects:[
      {title:'English',grade:'A'},
      {title:'Maths',grade:'A'},
      {title:'Science',grade:'B'},
      {title:'Geography',grade:'C'}
    ]
  };
  //create a filtered array of results 
  //with grade 'C' or subjects that have been failed
  $scope.failedSubjects = filterFilter($scope.results.subjects, {'grade':'C'});
}

Luego puede hacer referencia a FabSubjects de la misma manera que haría referencia al objeto de resultados

Puedes leer más sobre esto aquí https://docs.angularjs.org/guide/filter

Dado que esta respuesta angular ha actualizado la documentación, ahora recomiendan llamar al filtro

// update 
// eg: $filter('filter')(array, expression, comparator, anyPropertyKey);
// becomes
$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});
Kieran
fuente
¿Qué es filterFilter? ¿Es algún servicio o directiva? ¿Dónde está el código para filterFilter?
Mou
Es un servicio angular. Echa un vistazo al primer ejemplo en el enlace de arriba. (en el archivo scripts.js)
Kieran
aunque han cambiado la documentación filterFilter todavía funciona ..
Kieran
4

Puede también utilizar las funciones de $filter('filter'):

var foo = $filter('filter')($scope.results.subjects, function (item) {
  return item.grade !== 'A';
});
Nelu
fuente
4

Si está utilizando ES6, puede:

var sample = [1, 2, 3]

var result = sample.filter(elem => elem !== 2)

/* output */
[1, 3]

También tenga en cuenta que el filtro no actualiza la matriz existente, devolverá una nueva matriz filtrada cada vez.

Diego Venâncio
fuente
0

Aplicando el mismo filtro en HTML con múltiples columnas, solo ejemplo:

 variable = (array | filter : {Lookup1Id : subject.Lookup1Id, Lookup2Id : subject.Lookup2Id} : true)
Amay Kulkarni
fuente