Tabla de Contenidos

4.5 ng-options

En la primera unidad ya vimos cómo usar el tag <select> mediante la directiva ng-model. Lo que vamos a ver ahora es cómo rellenar todas sus opciones automáticamente a partir de los datos del $scope. Es algo parecido al tag ng-repeat que acabamos de ver y para ello se utiliza la directiva ng-options 1)

Antes de aplicar la directiva deberemos tener una variable en nuestro $scope con el array de datos a mostrar en el <select>.

app.controller("PruebaController", function($scope) {
  $scope.provincias=[
    {
      idProvincia:2,
      nombre:"Castellón"
    },
    {
      idProvincia:3,
      nombre:"Alicante"
    },
    {
      idProvincia:1,
      nombre:"Valencia"
    },
    {
      idProvincia:7,
      nombre:"Teruel"
    },  
    {
      idProvincia:5,
      nombre:"Tarragona"
    }
  ];
    
  $scope.miProvinciaSeleccionada=null

});

  • Línea 2 : Hemos definido la variable provincias con el array de provincias a mostrar en el tag <select>.
  • Línea 25: Propiedad miProvinciaSeleccionada asociada al <select> mediante ng-model y que es donde se guardará el valor seleccionado en el <select>. Los más importante es que contendrá el objeto correspondiente a la provincia que se ha seleccionado y no sólo su idProvincia.

Ahora que ya tenemos el modelo, pasemos a ver cómo usar la directiva ng-options.La forma es un poco compleja:

valor as etiqueta for item in items track by claveunica

Siendo:

  • items:La propiedad del $scope que contiene el array de elementos a mostrar en el <select>.
  • item:Es la declaración de una variable que contendrá cada uno de los elementos de items. Este valor puede ser cualquier texto que decidamos.
  • valor: Una expresión que use la variable item que será el valor que se asignará al modelo del <select>. En nuestro caso será el objeto entero.
  • etiqueta: Una expresión que use la variable item que será la etiqueta que se mostrará en cada uno de los <option>.
  • claveunica: La propiedad que es clave única.

En nuestro ejemplo quedará de la siguiente forma:

<select ng-model="miProvinciaSeleccionada" ng-options="provincia as provincia.nombre for provincia in provincias track by provincia.idProvincia" >
  <option value="">--Elige opcion--</option>
</select>

  • La lista de todos los valores se obtiene de provincias.
  • Cada uno de los elementos los referenciamos como provincia.
  • La etiqueta de cada uno de los <option> es provincia.nombre.
  • El valor que se asignará a la variable provincia del ng-model es la propia variable provincia de cada uno de los elementos.
  • La clave única es provincia.idProvincia

Otra forma de ver cómo funciona la directiva ng-options:

provincia as provincia.nombre for provincia in provincias

sería con el siguiente pseudocódigo en Java:

for(Provincia provincia:provincias) {
  valor=provincia;
  etiqueta=provincia.nombre;
}

Hay que fijarse en la potencia de AngularJS. El <select> no lo hemos asociado a un simple valor numérico como idProvincia sino con el objeto completo provincia.

Aunque nada impide asociarlo al idProvincia. Habría que modificar la directiva de la siguiente forma: “provincia.idProvincia as provincia.nombre for provincia in provincias”

En la línea 2 del HTML podemos ver cómo se ha añadido un <option> para el caso del valor null. Es recomendable añadir esta opción, ya que si no lo hará automáticamente AngularJS pero al seleccionar una provincia desaparecerá la opción vacía, lo que hace que sea muy extraño para el usuario.

En muchos ejemplos en internet de ng-options no se usa la parte de track by . Podríamos pensar que no es necesario ponerlo ya que es una simple optimización. Pues en caso de que estemos tratando con objetos en el ng-model, la mayoría de veces es un error no ponerlo.

Si quitamos track by provincia.idProvincia y modificamos la propiedad miProvinciaSeleccionada de la siguiente manera:

  $scope.miProvinciaSeleccionada={
      idProvincia:3,
      nombre:"Alicante"
    }

Veremos que no está seleccionada la provincia de Alicante. ¿Por qué no está seleccionada la provincia de Alicante? Porque realmente no hemos seleccionado ningún elemento del array. Se debería haber puesto:

  $scope.miProvinciaSeleccionada=$scope.provincias[1];

Puesto que $scope.provincias[1] no es igual a { idProvincia:3, nombre:“Alicante”} aunque tengan los mismo valores. Realmente son 2 objetos distintos ya que apuntan a zonas de memoria distintas.

Añadiendo a ng-options el texto track by provincia.idProvincia le decimos a AngularJS que compare cada objeto por la propiedad idProvincia, por lo que el objeto $scope.provincias[1] ya es igual a { idProvincia:3, nombre:“Alicante”} ya que el idProvincia de $scope.provincias[1] es 3

¿Y es realmente útil? Si , cuando tengamos el array y a la variable $scope.miProvinciaSeleccionada se le asigne un objeto desde el servidor querremos que lo seleccione aunque no sea el mismo objeto.

Si el valor es un escalar como un String o un número no es necesario poner el track by si no es por temas de optimización.

Ejemplo

El ejemplo completo quedaría de la siguiente forma:

<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.js"></script>
  <script src="script.js"></script>
</head>

<body ng-controller="PruebaController">

      <select ng-model="miProvinciaSeleccionada" ng-options="provincia as provincia.nombre for provincia in provincias track by provincia.idProvincia" >
        <option value="">--Elige opcion--</option>
      </select>
      <br>
      El nombre de la provincia seleccionada es:{{miProvinciaSeleccionada.nombre}}
      
</body>

</html>

var app = angular.module("app", []);
 
app.controller("PruebaController", function($scope) {
  $scope.provincias=[
    {
      idProvincia:2,
      nombre:"Castellón"
    },
    {
      idProvincia:3,
      nombre:"Alicante"
    },
    {
      idProvincia:1,
      nombre:"Valencia"
    },
    {
      idProvincia:7,
      nombre:"Teruel"
    },  
    {
      idProvincia:5,
      nombre:"Tarragona"
    }
  ];
    
  $scope.miProvinciaSeleccionada={
      idProvincia:3,
      nombre:"Alicante"
    }

});

Referencias

1) Estrictamente hablando ng-options no es una directiva sino que es simplemente un atributo de la directiva select asociada al tag <select>
unidades/04_masdirectivas/05_ngoptions.txt · Última modificación: 2014/11/07 20:45 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