Respuesta corta : ¿realmente necesita esa función o puede usar la propiedad? http://jsfiddle.net/awnqm/1/
Respuesta larga
Por simplicidad, describiré solo su caso: ngRepeat para una matriz de objetos. Además, omitiré algunos detalles.
AngularJS usa verificación sucia para detectar cambios. Cuando se inicia la aplicación que se ejecuta $digest
para $rootScope
. $digest
hará un recorrido en profundidad primero para la jerarquía del alcance . Todos los alcances tienen lista de relojes. Cada reloj tiene el último valor (inicialmente initWatchVal
). Para cada alcance de todos los relojes, lo $digest
ejecuta, obtiene el valor actual ( watch.get(scope)
) y lo compara con watch.last
. Si el valor actual no es igual a watch.last
(siempre para la primera comparación) se $digest
establece dirty
en true
. Cuando se procesan todos los ámbitos, dirty == true
$digest
comienza otro recorrido en profundidad desde $rootScope
. $digest
termina cuando está sucio == falso o número de recorridos == 10. En el último caso, el error "10 $ digest () iteraciones alcanzadas". se registrará.
Ahora sobre ngRepeat
. Para cada watch.get
llamada, almacena objetos de la colección (valor de retorno de getEntities
) con información adicional en caché ( HashQueueMap
por hashKey
). Para cada watch.get
llamada, ngRepeat
intenta obtener un objeto por su hashKey
caché. Si no existe en la memoria caché, ngRepeat
lo almacena en la memoria caché, crea nuevas posibilidades, pone objeto en ella, crea elemento DOM, etc .
Ahora sobre hashKey
. Generalmente hashKey
es un número único generado por nextUid()
. Pero puede ser funcional . hashKey
se almacena en el objeto después de generarlo para uso futuro.
Por qué su ejemplo genera error : la función getEntities()
siempre devuelve una matriz con un nuevo objeto. Este objeto no tiene hashKey
ni existe en la ngRepeat
caché. Entonces ngRepeat
en cada uno watch.get
genera un nuevo alcance para él con un nuevo reloj {{entity.id}}
. Este primer reloj watch.get
tiene watch.last == initWatchVal
. Entonces watch.get() != watch.last
. Entonces $digest
comienza una nueva travesía. Entonces ngRepeat
crea un nuevo alcance con un nuevo reloj. Entonces ... después de 10 recorridos obtienes un error.
¿Cómo puedes arreglarlo?
- No cree nuevos objetos en cada
getEntities()
llamada.
- Si necesita crear nuevos objetos, puede agregar un
hashKey
método para ellos. Consulte este tema para ver ejemplos.
Espero que las personas que conocen los componentes internos de AngularJS me corrijan si me equivoco en algo.
Do not create new objects on every getEntities() call.
se puede arreglar bastante fácilmente así:<div ng-repeat="entity in entities = (entities || getEntities())">
getEntities()
siempre devuelva la misma matriz, si la matriz alguna vez cambia, no la obtendrá en elng-repeat
Inicializar la matriz fuera de la repetición
fuente
getEntities()
devuelve algo diferente en el ciclo de vida del programa. Digamos, por ejemplo, quegetEntities()
desencadena un$http.get
. Cuando el get finalmente se resuelva (realizó la llamada AJAX),entities
ya estará inicializado.The only appropriate use of ngInit is for aliasing special properties of ngRepeat. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
Esto se informó aquí y obtuvo esta respuesta:
Puede ver que este comportamiento desaparece si mueve la matriz fuera del controlador principal:
porque ahora devuelve el mismo objeto cada vez. Es posible que deba rediseñar su modelo para usar una propiedad en el alcance en lugar de una función:
fuente
Basado en el comentario de @przno
Por cierto, la segunda solución @Artem Andreev sugiere que no funciona en Angular 1.1.4 y superior, mientras que la primera no resuelve el problema. Entonces, me temo que por ahora esta es la solución menos puntiaguda sin desventajas en la funcionalidad
fuente
Item.id
es lo que debería b. Gracias