> Manuales > Manual de Angular

Explicamos la directiva ngFor, o *ngFor, que nos permite repetir una serie de veces un bloque de HTML en aplicaciones Angular 2.

En este artículo vamos a conocer y practicar con una directiva de las más importantes en Angular 2, que es la directiva ngFor, capaz de hacer una repetición de elementos dentro de la página. Esta repetición nos permite recorrer una estructura de array y para cada uno de sus elementos replicar una cantidad de elementos en el DOM.

Para los que vengan de Angular 1 les sonará, puesto que es lo mismo que ya se conoce de ngRepeat, aunque cambian algunas cosillas sobre la sintaxis para la expresión del bucle, así como algunos mecanismos como la ordenación.

Uso básico de ngFor

Para ver un ejemplo de esta directiva en funcionamiento estamos obligados a crear de antemano un array con datos, que deben ser enviados a la vista, para que ya en el HTML se pueda realizar esa repetición. Como todo en Angular 2 se organiza mediante un componentes, vamos a crear un componente que contiene lo necesario para poder usar esta el ngFor.

Comenzamos con el código de la parte de TypeScript, que es donde tendremos que crear los datos que estarán disponibles en la vista.

import { Component, OnInit } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app-listado-preguntas',
  templateUrl: 'listado-preguntas.component.html',
  styleUrls: ['listado-preguntas.component.css']
})
export class ListadoPreguntasComponent implements OnInit {

  preguntas: string[] = [
    "¿España ganará la Euro 2016?",
    "¿Hará sol el día de mi boda?",
    "¿Estás aprendiendo Angular 2 en DesarrolloWeb?",
    "¿Has hecho ya algún curso en EscuelaIT?"
  ];

  ngOnInit() {
  }

}

Este código nos debe de sonar, pues es el boilerplate de un componente (creado mediante Angular CLI) al que le hemos agregado la declaración de una propiedad de tipo array de strings.

Nota: Hemos asignado el valor de ese array de manera literal, pero lo normal sería que lo obtengas de alguna fuente como un servicio web, API, etc.

Luego, veamos el código HTML de este componente, que es donde colocamos la directiva ngFor.

<p *ngFor="let pregunta of preguntas">
  {{pregunta}}
</p>

Es algo muy sencillo, simplemente tenemos un párrafo que se repetirá un número de veces, una por cada elemento del array de preguntas. En este caso es un párrafo simple, pero si dentro de él tuviéramos más elementos, también se repetirían. Lo que tenemos que analizar con detalle es el uso de la directiva, aunque creemos que se auto-explica perfectamente.

*ngFor="let pregunta of preguntas"

Lo primero que verás es un símbolo asterisco (*) que quizás parezca un poco extraño. No es más que "azúcar sintáctico" para recordarnos que estas directivas (las comenzadas por el asterisco) afectan al DOM, produciendo la inserción, manipulación o borrado de elementos del mismo.

Nota: En las explicaciones que encontrarás en la documentación de Angular 2 sobre el origen del asterisco en el nombre de la directiva nos mencionan detalles acerca de su implementación a bajo nivel, indicando que para ello se basan en el tag TEMPLATE, uno de las especificaciones nativas de Web Components.

Como valor de la directiva verás que se declara de manera interna para este bucle una variable "pregunta", que tomará como valor cada uno de los valores del array en cada una de sus repeticiones.

Nota: "let" es una forma de declarar variables en Javascript ES6. Quiere decir que aquella variable sólo tendrá validez dentro del bloque donde se declara. En este caso "de manera interna" nos referimos a que "pregunta" solo tendrá validez en la etiqueta que tiene el ngFor y cualquiera de sus los elementos hijo.

Recorrido a arrays con objetos con ngFor

Generalmente ngFor lo usarás para recorrer arrays que seguramente tendrán como valor en cada una de sus casillas un objeto. Esto no cambia mucho con respecto a lo que ya hemos visto en este artículo, pero sí es una bonita oportunidad de aprender algo nuevo con TypeScript.

De momento veamos las cosas sin TypeScript para ir progresivamente. Así sería cómo quedaría la declaración de nuestro array, al que todavía no indicaremos el tipo para no liarnos.

preguntasObj = [
    {
      pregunta: "¿España ganará la Euro 2016?",
      si: 22,
      no: 95
    },
    {
      pregunta: "¿Estás aprendiendo Angular 2 en DesarrolloWeb??",
      si: 262,
      no: 3
    },
    {
      pregunta: "¿Has hecho ya algún curso en EscuelaIT??",
      si: 1026,
      no: 1
    }
  ]

Como ves, lo que antes era un array de strings simples ha pasado a ser un array de objetos. Cada uno de los objetos nos describen tanto la pregunta en sí como las respuestas positivas y negativas que se han recibido hasta el momento.

Ahora, al usarlo en la vista, el HTML, podemos mostrar todos los datos de cada objeto, con un código que podría ser parecido a este:

<p *ngFor="let objPregunta of preguntasObj">
  {{objPregunta.pregunta}}: 
  <br>
  <span class="si">Si {{objPregunta.si}}</span> / 
  <span class="no">No {{objPregunta.no}}</span>
</p>

Como ves en este código, dentro del párrafo tengo acceso a la pregunta, que al ser un objeto, contiene diversas propiedades que uso para mostrar los datos completos de cada item.

Modificación implementando Interfaces TypeScript

Como has visto, no existe mucha diferencia con respecto a lo que teníamos, pero ahora vamos a darle un uso a TypeScript que nos permitirá experimentar algo que nos aporta el lenguaje: interfaces.

En este caso vamos a usar las interfaces simplemente para definir un tipo de datos para las preguntas, un esquema para nuestros objetos pregunta. En este caso solo lo vamos a usar para que, a la hora de escribir código, el editor nos pueda ayudar indicando errores en caso que la interfaz no se cumpla. Así, a la hora de escribir código podremos estar seguros que todas las preguntas con las que trabajemos tengan los datos que son necesarios para la aplicación.

Nota: Las interfaces que se sabe son mecanismos para solventar las carencias de herencia múltiple, en este caso las vamos a usar como una simple definición de tipos.

Algo tan sencillo como esto:

interface PreguntasInterface {
  pregunta: string;
  si: number;
  no: number;
}

Permite a TypeScript conocer el esquema de un objeto pregunta. Ahora, apoyándonos en esa interfaz podrás declarar tu array de preguntas de esta manera.

preguntasObj: PreguntasInterface[] = [
    {
      pregunta: "¿Te gusta usar interfaces?",
      si: 72,
      no: 6
    }
]

Ahora estamos indicando el tipo de los elementos del array, diciéndole que debe concordar con lo definido en la interfaz. ¿Te gusta? Quizás ahora no aprecies mucha diferencia, pero esto se puede usar para varias cosas, significando una ayuda en la etapa de desarrollo, y sin afectar al rendimiento de la aplicación, puesto que las interfaces en TypeScript una vez transpilado el código no generan código alguno en Javascript.

Nota: Lo normal es que coloques el código de la interfaz en un archivo independiente y que hagas el correspondiente "import". Recordando que Angular CLI tiene un comando para generar interfaces que te puede resultar útil. De momento si lo deseas, a modo de prueba lo puedes colocar en el mismo archivo que el código TypeScript del componente.

Quizás para los que no estén acostumbrados a TypeScript sea difícil hacerse una idea exacta sobre cómo te ayudaría el editor de código por el simple hecho de usar esa interfaz. Para ilustrarlo hemos creado este vídeo en el que mostramos las ayudas contextuales cuando estamos desarrollando con Visual Studio Code.

Hablaremos más sobre interfaces en otras ocasiones. Ahora el objetivo era simplemente ver una pequeña muestra de las utilidades que podría aportarnos.

Como habrás visto no es difícil entender esta directiva, pero ten en cuenta que hemos visto lo esencial sobre las repeticiones con ngFor. Hay mucho más que habría que comentar en un futuro, acerca de usos un poco más avanzados como podría ser la ordenación de los elementos del listado.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual