Directiva AngularJS ng-repeat con ejemplo
⚡ Resumen inteligente
La directiva ng-repeat en AngularJS renderiza una copia de un elemento por cada elemento de una colección definida en el ámbito del controlador. Convierte un array en una lista, una tabla o cualquier marcado repetitivo sin necesidad de escribir un bucle manualmente.
Directiva ng-repeat en AngularJS
El ng-repetir Directivas En AngularJS, se utiliza para mostrar valores repetidos definidos en el controlador. A veces necesitamos mostrar una lista de elementos en la vista, y ng-repeat renderiza una lista definida en el controlador en una página de vista.
⚠️ Aviso de soporte: AngularJS alcanzó fin de vida el 31 de diciembre de 2021 y no recibe más parches ni correcciones de seguridad. La directiva que aparece a continuación sigue siendo válida para el mantenimiento de aplicaciones AngularJS 1.x existentes; en versiones modernas Angular el equivalente es el *ngFor directiva estructural.
Ejemplo de directiva ng-repeat de AngularJS
Veamos un ejemplo de la directiva ng-repeat en AngularJS:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> </head> <body> <h1>Guru99 Global Event</h1> <script src="https://code.angularjs.org/1.8.3/angular.js"></script> <div ng-app="DemoApp" ng-controller="DemoController"> <h1>Topics</h1> <ul> <li ng-repeat="tpname in TopicNames"> {{tpname.name}} </li> </ul> </div> <script> var app = angular.module('DemoApp', []); app.controller('DemoController', function($scope) { $scope.TopicNames = [ { name: "What controllers do from Angular's perspective" }, { name: "Controller Methods" }, { name: "Building a basic controller" } ]; }); </script> </body> </html>
Code Explicación:
- En la sección controlador, primero definimos la matriz de elementos de la lista que se mostrarán en la vista. Aquí una matriz llamada
TopicNamesContiene tres elementos, cada uno un par nombre-valor. - El array se asigna directamente a
$scope.TopicNames, lo que lo hace disponible para la vista vinculada a este controlador. - Las etiquetas HTML
<ul>(lista no ordenada) y<li>(elemento de lista) muestra los elementos. La directiva ng-repeat itera sobre cada entrada en la matriz, ytpnamees la variable local que contiene el elemento actual, por lo que{{tpname.name}}imprime su propiedad de nombre.
⚠️ Corrección: La explicación original indicaba que la matriz se había “añadido a una variable miembro llamada topics“. No existe tal variable en el código; el array se asigna directamente a $scope.TopicNames, que es el nombre al que se refiere la vista. Introducir un segundo nombre aquí es una causa común de que la lista quede vacía.
Si el código se ejecuta correctamente, se muestra la siguiente salida en el navegador.
AngularJS múltiples controladores
Anteriormente vimos un único controlador en el que un método manejaba tanto la suma como la resta.tracción de números. En su lugar, puede usar varios controladores para separar la lógica de forma más clara. Por ejemplo, un controlador puede operar con números mientras que otro opera con cadenas.
Veamos un ejemplo de cómo definir varios controladores en una aplicación AngularJS.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> </head> <body> <h1>Guru99 Global Event</h1> <script src="https://code.angularjs.org/1.8.3/angular.js"></script> <div ng-app="DemoApp"> <div ng-controller="firstcontroller"> <div ng-controller="secondcontroller"> {{lname}} </div> </div> </div> <script> var app = angular.module('DemoApp', []); app.controller('firstcontroller', function($scope) { $scope.pname = "firstcontroller"; }); app.controller('secondcontroller', function($scope) { $scope.lname = "secondcontroller"; }); </script> </body> </html>
Code Explicación:
- Se definen dos controladores,
firstcontrollerysecondcontrollerCada uno adjunta una variable a su propio global:pnameen el primero,lnameen el segundo. - En la vista, el segundo controlador está anidado dentro del primero, y la expresión dice:
lnamedesde el ámbito interno. Debido a que un controlador anidado hereda de su padre,{{pname}}Esto también se resolvería aquí: la herencia fluye hacia abajo, nunca hacia arriba.
Si el código se ejecuta correctamente, el texto segundo controlador se visualiza.
Instrucciones de uso track por con ng-repeat
El fallo más común de ng-repeat es el error Duplicates in a repeater are not allowedAparece en el momento en que una colección contiene el mismo valor dos veces, y detiene por completo la representación de la lista.
La causa es la identidad tracAngularJS necesita una clave estable para cada elemento, de modo que pueda reutilizar los nodos DOM en lugar de reconstruirlos en cada ciclo de digestión. Por defecto, utiliza el valor del elemento en sí, por lo que dos valores idénticos entran en conflicto.
<!-- Fails: the value 2 appears twice --> <li ng-repeat="n in [1, 2, 2, 3]">{{n}}</li> <!-- Works: position is unique even when values repeat --> <li ng-repeat="n in [1, 2, 2, 3] track by $index">{{n}}</li> <!-- Mejores for records from a server: track by a real identifier --> <li ng-repeat="topic in TopicNames track by topic.id">{{topic.name}}</li>
Elegir entre las dos formas es más importante de lo que parece a primera vista. Tracking by $index siempre resuelve el error, porque una posición es única por definición, pero vincula cada nodo DOM a una ranura en lugar de a un registro. Reordenar o filtrar la colección luego reutiliza los nodos incorrectos, lo que aparece como campos de entrada que se mantienen.ping el texto de la fila anterior.
Tracking mediante un identificador genuino como topic.id lo evita por completo. AngularJS puede seguir cada registro a medida que se mueve, por lo que reordena los nodos existentes en lugar de destruirlos y reconstruirlos. En listas largas, esto también es notablemente más rápido, ya que una nueva renderización solo afecta a las filas que realmente cambiaron. $index solo para matrices de valores simples que nunca se reordenan.
Propiedades especiales disponibles dentro de ng-repeat
Cada iteración de ng-repeat expone varias propiedades de solo lectura en su propio ámbito secundario. Estas propiedades describen la posición del elemento actual dentro de la colección, lo que incluye la numeración, los estilos alternos y los separadores, sin agregar ningún estado adicional al controlador.
| Propiedad | Tipo | Valor |
|---|---|---|
$index |
Número | Posición del elemento actual, comenzando en 0 |
$first |
Boolean | Esto solo aplica al primer artículo. |
$last |
Boolean | Esto solo aplica al último elemento. |
$middle |
Boolean | Esto es cierto para todos los elementos que no son ni el primero ni el último. |
$even |
Boolean | Verdadero cuando $index es par |
$odd |
Boolean | Verdadero cuando $index es impar |
Un uso típico los combina con ng-class para zebra striping, como en ng-class="{'row-alt': $odd}"o con ng-if para mostrar un separador en cada fila excepto en la última, escrita ng-if="!$last"Mostrar un número de fila legible para humanos es simplemente {{$index + 1}}Dado que el índice comienza en cero, las seis propiedades se recalculan automáticamente cada vez que cambia la colección, por lo que no es necesario volver a calcular nada manualmente.
Errores comunes de ng-repeat y cómo solucionarlos
La mayoría de los problemas con ng-repeat se deben a valores duplicados, a la herencia del ámbito o a que la directiva se encuentra en el elemento incorrecto. Cada síntoma que se describe a continuación indica su causa.
- No se permiten duplicados en un repetidor: La colección contiene un valor repetido. Agregar
track by $index, o mejor,track byuna propiedad única. - La lista no devuelve nada: El nombre en la vista no coincide con la propiedad en el ámbito. Imprime la colección con
{{TopicNames}}para confirmar que llegó. - Todos los elementos se repiten, incluido el contenedor: ng-repeat se colocó en el contenedor en lugar de en el elemento. Muévalo al
<li>or<tr>. - Al editar un campo de entrada, se modifica la fila incorrecta: La lista es tracAdorado por
$indexmientras se reordenan los artículos. Track por un identificador estable en su lugar. - Los cambios dentro del bucle no se conservan: cada iteración tiene su propio ámbito hijo, por lo que escribir en un tipo primitivo crea una copia local. Escriba en una propiedad de objeto, como
item.done.





