Réponse courte : avez-vous vraiment besoin d'une telle fonction ou pouvez-vous utiliser la propriété? http://jsfiddle.net/awnqm/1/
Longue réponse
Pour simplifier, je ne décrirai que votre cas - ngRepeat pour un tableau d'objets. Aussi, je vais omettre certains détails.
AngularJS utilise la vérification sale pour détecter les changements. Lorsque l' application est lancée , elle fonctionne $digest
pour $rootScope
. $digest
effectuera une traversée en profondeur pour la hiérarchie de la portée . Toutes les lunettes ont une liste de montres. Chaque montre a la dernière valeur (initialement initWatchVal
). Pour chaque portée de toutes les montres $digest
, il l'exécute, obtient la valeur actuelle ( watch.get(scope)
) et la compare à watch.last
. Si la valeur actuelle n'est pas égale à watch.last
(toujours pour la première comparaison), la valeur est $digest
définie dirty
sur true
. Lorsque toutes les étendues sont traitées, si dirty == true
$digest
commence une autre traversée en profondeur à partir de $rootScope
. $digest
se termine quand dirty == false ou nombre de traversées == 10. Dans ce dernier cas, l'erreur "10 $ digest () iterations atteints." sera enregistré.
Maintenant environ ngRepeat
. Pour chaque watch.get
appel, il stocke les objets de la collection (valeur de retour de getEntities
) avec des informations supplémentaires dans le cache ( HashQueueMap
par hashKey
). Pour chaque watch.get
appel ngRepeat
essaie d'obtenir un objet par son hashKey
du cache. Si elle n'existe pas dans le cache, ngRepeat
il stocke dans le cache, crée de nouvelles possibilités, met objet sur elle, crée élément DOM, etc .
Maintenant environ hashKey
. Il hashKey
s'agit généralement d' un numéro unique généré par nextUid()
. Mais cela peut être une fonction . hashKey
est stocké dans l'objet après la génération pour une utilisation future.
Pourquoi votre exemple génère une erreur : la fonction getEntities()
renvoie toujours un tableau avec un nouvel objet. Cet objet n'a pas hashKey
et n'existe pas dans le ngRepeat
cache. Ainsi ngRepeat
, chacun watch.get
génère une nouvelle portée pour cela avec une nouvelle montre pour {{entity.id}}
. Cette montre le premier watch.get
a watch.last == initWatchVal
. Alors watch.get() != watch.last
. Alors $digest
commence une nouvelle traversée. Crée donc une ngRepeat
nouvelle portée avec une nouvelle montre. Donc ... après 10 traversées, vous obtenez une erreur.
Comment vous pouvez y remédier
- Ne créez pas de nouveaux objets à chaque
getEntities()
appel.
- Si vous avez besoin de créer de nouveaux objets, vous pouvez leur ajouter une
hashKey
méthode. Consultez cette rubrique pour des exemples.
J'espère que les gens qui connaissent les composants internes d'AngularJS me corrigeront si je me trompe dans quelque chose.
Do not create new objects on every getEntities() call.
peut être corrigé assez facilement comme ceci:<div ng-repeat="entity in entities = (entities || getEntities())">
getEntities()
retourne toujours le même tableau, si le tableau change un jour, vous ne l'obtiendrez pas dans leng-repeat
Initialiser le tableau en dehors de la répétition
la source
getEntities()
renvoie quelque chose de différent dans le cycle de vie du programme. Disons, par exemple, que celagetEntities()
déclenche un$http.get
. Lorsque le get enfin résoudre (vous avez effectué l'appel AJAX),entities
sera déjà initialisé.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.
Cela a été signalé ici et a obtenu cette réponse:
Vous pouvez voir ce comportement disparaître si vous déplacez la baie hors du contrôleur principal:
car maintenant il renvoie le même objet à chaque fois. Vous devrez peut-être réorganiser votre modèle pour utiliser une propriété sur la portée au lieu d'une fonction:
la source
Basé sur le commentaire de @przno
La deuxième solution de BTW @Artem Andreev suggère qu'elle ne fonctionne pas dans Angular 1.1.4 et supérieur, tandis que la première ne résout pas le problème. Donc, j'ai peur pour l'instant que ce soit la solution la moins épineuse sans inconvénients de fonctionnalité
la source
Item.id
est ce qu'il devrait b. Merci