5.4 Filter

El filtro filter , cuyo nombre es poco afortunado, filtra el array para que el array resultante sólo tenga ciertos datos del array original

Este filtro soporta varios tipos de parámetros así que vamos a verlos uno por uno.

En todos los ejemplos vamos a suponer los siguientes datos:

    $scope.provincias = [{
        idProvincia: 1,
        nombre: "Palencia",
        comunidadAutonoma:"Castilla-Leon",
        idiomasCooficiales:false
    }, {
        idProvincia: 2,
        nombre: "Castellón",
        comunidadAutonoma:"Valencia",
        idiomasCooficiales:true
    }, {
        idProvincia: 3,
        nombre: "Alicante",
        comunidadAutonoma:"Valencia",
        idiomasCooficiales:true    
    }];

Búsqueda en todas las propiedades

Vamos a ver cómo buscar un texto que esté en cualquiera de las propiedades de los objetos del array. Pero no hace falta que el texto y la propiedad coincidan exactamente sino sólo una parte. Haciendo un símil con SQL es como si se hiciera un ” propiedad LIKE '%texto%' ” y usando todas las propiedades de cada objeto del array.

formato:

{{ valor | filter:texto }}

Siendo texto un String con el texto a buscar en cualquier propiedad de los objetos de array.

Si aplicamos el filtro de la siguiente forma:

<tr ng-repeat="provincia in provincias | filter:'encia'">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Mostrará las 3 provincias ya que el texto “encia” está en la propiedad nombre de “Palencia” y en la propiedad “comunidadAutonoma” de “Alicante” y “Castellón”.

Búsqueda en una propiedad

Podemos restringir para que se busque en sólo una propiedad de la siguiente forma:

formato:

{{ valor | filter:{ propiedad:texto } }}

Siendo texto un String con el texto a buscar en la propiedad llamada propiedad

<tr ng-repeat="provincia in provincias | filter:{ nombre:'encia'}'">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Ahora sólo busca el texto “encia” en la propiedad nombre.

Búsqueda en varias propiedades

Si queremos buscar en más de una propiedad y haciendo un AND entre ellas podemos usar:

formato:

{{ valor | filter:{ propiedad1:texto1, propiedad2:texto2 } }}

<tr ng-repeat="provincia in provincias | filter:{ nombre:'encia',comunidadAutonoma:'illa'}'">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Ahora sólo buscará aquellas provincias cuyo nombre contenga el texto “encia” y cuya comunidad autónoma contenga el texto “illa”.

Búsqueda combinada

Usando el nombre de propiedad “$” se puede buscar un texto en todas las propiedades pero además añadir otra condición con un AND como acabamos de hacer. Es decir que la propiedad “$” es como si fuera el nombre de cualquier propiedad.

Veamos un ejemplo:

<tr ng-repeat="provincia in provincias | filter:{ $:'encia',idiomasCooficiales:true}'">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Ahora buscará el texto “encia” en cualquier propiedad pero además la propiedad idiomasCooficiales debe ser true.

Vemos que es una ventaja usar

array | filter:{$:texto}

con respecto a simplemente usar

array | filter:texto

ya que en el primer caso podemos añadir condiciones AND con el formato

array | filter:{$:texto,propiedad:valor}

mientras que en el segundo caso no se puede.

Comparador

Hemos visto que el filtro filter comprueba que lo que buscamos esté contenido dentro de la propiedad en la que buscamos, pero ¿y si queremos que solo lo encuentre si es la palabra entera? ¿Y si queremos que encuentre una palabra sólo si empieza por el texto por el que se filtra?, etc. , etc.

Para ayudarnos en todo ésto, el filtro filter dispone de un segundo parámetro que permite indicar cómo se hace la comparación entre los textos, veamos los 3 posibles valores.

false

Poner false es la funcionalidad por defecto, por lo tanto es lo mismo que no poner nada. Y como ya hemos dicho, buscará que el texto a buscar esté contenido en la propiedad. Es como en SQL propiedad LIKE ”%textoBuscar%”.

<tr ng-repeat="provincia in provincias | filter:{ nombre:'encia'}:false">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Busca en la propiedad “nombre” si contiene la palabra “encia”.

true

Si se pone el valor true, en este caso el texto a buscar debe ser igual al valor de la propiedad. Es como en SQL propiedad = textoBuscar

<tr ng-repeat="provincia in provincias | filter:{ nombre:'encia'}:true">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Busca en la propiedad “nombre” si su valor es exactamente la palabra “encia”.

funcion

En este caso no ponemos un valor booleano como true o false sino el nombre de una función creada por nosotros en el $scope y a la que se le pasarán 2 argumentos. El primer argumento es el valor de la propiedad y el segundo argumento es el texto a buscar. Si la función retorna true es que son iguales y si retorna false es que son distintos.

En nuestro ejemplo vamos a suponer que tenemos la siguiente función en el $scope

    $scope.comparator = function(actual, expected) {
        if (actual.indexOf(expected)===0) {
          return true;
        } else {
          return false;
        }
    }; 
Esta función retorna true si el valor de actual comienza por el valor de expected

<tr ng-repeat="provincia in provincias | filter:{ nombre:'encia'}:comparator">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

Busca en la propiedad “nombre” si su valor comienza con la palabra “encia”.Para hacerlo lo que hace es llamar a la función comparator que como ya hemos explicado sólo retorna true si el valor comienza por la palabra buscada.

Veamos una tabla comparando más características de los 3 modos:

Valor parámetro El texto a buscar es ”“ Sensible a mayúsculas/minusculas Sensible a acentos, diéresis, etc.
false1) Se retornan todas las filas NO 2) Deben coincidir los acentos, diéresis, etc.
true No se retorna ninguna fila SI 3) Deben coincidir los acentos, diéresis, etc.
Función JavaScript Personalizado según lo que haga la función Personalizado según lo que haga la función Personalizado según lo que haga la función

Como vemos el usar una función nos permite personalizar todo lo que queremos, como comparar los datos, aunque realmente no permite cambiar la consulta de búsqueda sino sólo la forma de comparar los 2 datos.

internacionalización

Aunque seguro que podrías hacerlo , aquí pongo un ejemplo de función de comparación para Strings que es insensible a mayúsculas / minúsculas pero que también encuentra los elementos independientemente de los acentos, diéresis y circunflejos:

    /** 
     * Esta función cambia todas las vocales con acentos, diéresis y circunflejos
     * por la vocal sin ellos y también la transforma a mayúsculas.
     */
    function normalize(texto) {
      texto = texto.replace(/[áàäâ]/g, "a");
      texto = texto.replace(/[éèëê]/g, "e");
      texto = texto.replace(/[íìïî]/g, "i");
      texto = texto.replace(/[óòôö]/g, "o");
      texto = texto.replace(/[úùüü]/g, "u");
      texto = texto.toUpperCase();
      return texto;
    }

    /** Esta función se puede usar como comparator en el filter **/
    $scope.comparator = function(actual, expected) {
        if (normalize(actual).indexOf(normalize(expected))>=0) {
          return true;
        } else {
          return false;
        }
    };

  • Línea 5: Esta función transforma cualquier texto quitando a cualquier vocal los acentos, diéresis y circunflejos.
  • Línea 16: Esta es la función de comparación que usaremos en filter. Su entrada son los 2 textos a comparar.
  • Línea 17: Esta línea transforma los 2 textos usando la función normalize que quita los acentos, diéresis y circunflejos. Entonces al estar libre de ellos, simplemente los compara usando la función indexOf.

Ahora podríamos usar nuestra función comparator en filter y encontraría cualquier palabra aunque escribamos mal los acentos, diéresis o circunflejos.

Búsqueda personalizada

Hasta ahora hemos visto cómo hacer filtros mirando en varias propiedades pero siempre era haciendo un AND entre ellas. AngularJS permite que le pasemos una función para que decidamos por nosotros mismos cómo filtrar los datos permitiendo hacer filtros todo lo complejos que queramos. En ese caso al filtro filter se le pasa un único parámetro con el nombre de una función creada por nosotros en el $scope . Dicha función acepta un único parámetro con un elemento de array y deberemos retornar true en caso de que queramos que ese elemento se muestre y false si no queremos que se muestre.

Veamos un ejemplo. Supongamos que en el $scope tenemos la siguiente función:

    $scope.consultaPersonalizada=function(value) {
      if ((value.idiomasCooficiales===true) || (value.idProvincia>2)) {
        return true;
      } else {
        return false;
      }
    }

Es una función a la que le pasaremos un valor del array y nos retorna true si value.idiomasCooficiales===true OR value.idProvincia>2. Observa cómo hemos usado el operador OR que hasta ahora no habíamos podido usar.

Ahora podemos simplemente usar esa función en el filtro filter.

<tr ng-repeat="provincia in provincias | filter:consultaPersonalizada">
  <td>{{provincia.codProvincia}}</td>
  <td>{{provincia.nombre}}</td>
</tr>

En ese caso sólo se mostrarán aquellas provincias que tengan un idioma cooficial y cuyo idProvincia sea mayor que 2

En caso de usar la función personalizada de filtro ya no se puede pasar un segundo argumento con la función de comparator ya que no tiene sentido pues la función personalizada de filtro se encarga de hacer todo el trabajo.

Ejemplo

En ese ejemplo podemos escribir en la caja de texto y podremos ver 3 ejemplos de cómo se comparan los datos en el filtro con:

  • false
  • true
  • función personalizada de comparación que sólo retorna true si el texto a buscar está al principio del valor de la propiedad pero que es sensible a mayúsculas / minúsculas.

Prueba a escribir:

  • ca
  • Ca
  • llón
  • llon
  • Castellón
  • castellon

Y observa cómo funciona cada una de las 3 formas.

Por último hay una última tabla en la que se ve la función personalizada.

Referencias

1) Por defecto
2) Se encuentra independientemente de las mayúsculas / minúsculas
3) Deben coincidir las mayúsculas / minúsculas
unidades/05_filtros/04_filter.txt · Última modificación: 2014/09/11 14:20 por admin
Ir hasta arriba
CC Attribution-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0