Resposta curta : você realmente precisa dessa função ou pode usar propriedade? http://jsfiddle.net/awnqm/1/
Resposta longa
Para simplificar, descreverei apenas seu caso - ngRepeat para array de objetos. Além disso, omitirei alguns detalhes.
O AngularJS usa verificação suja para detectar alterações. Quando a aplicação é iniciada corre $digest
para $rootScope
. $digest
fará a travessia em profundidade para a hierarquia do escopo . Todos os escopos têm lista de relógios. Cada relógio tem o último valor (inicialmente initWatchVal
). Para cada escopo para todos os relógios o $digest
executa, obtém o valor atual ( watch.get(scope)
) e o compara com watch.last
. Se o valor atual não for igual a watch.last
(sempre na primeira comparação), $digest
defina dirty
como true
. Quando todos os escopos são processados, ele dirty == true
$digest
inicia outro percurso em profundidade de $rootScope
. $digest
termina quando sujo == falso ou número de travessias == 10. No último caso, o erro "10 $ digest () iterações alcançadas." será registrado.
Agora sobre ngRepeat
. Para cada watch.get
chamada, ele armazena objetos da coleção (valor de retorno de getEntities
) com informações adicionais no cache ( HashQueueMap
por hashKey
). Para cada watch.get
chamada ngRepeat
tenta obter o objeto por meio hashKey
do cache. Se ele não existir no cache, ngRepeat
armazena em cache, cria novo escopo, coloca objeto sobre ele, cria elemento DOM, etc .
Agora sobre hashKey
. Normalmente hashKey
é um número único gerado por nextUid()
. Mas pode ser função . hashKey
é armazenado no objeto após a geração para uso futuro.
Por que seu exemplo gera erro : a função getEntities()
sempre retorna o array com o novo objeto. Este objeto não tem hashKey
e não existe no ngRepeat
cache. Assim, ngRepeat
cada um watch.get
gera um novo escopo para ele com um novo relógio {{entity.id}}
. Este relógio primeiro watch.get
tem watch.last == initWatchVal
. Então watch.get() != watch.last
. Então $digest
começa uma nova travessia. Portanto, ngRepeat
cria um novo escopo com o novo relógio. Então ... após 10 travessias você obtém um erro.
Como você pode consertar isso
- Não crie novos objetos em cada
getEntities()
chamada.
- Se você precisa criar novos objetos, você pode adicionar
hashKey
métodos para eles. Veja este tópico para exemplos.
Espero que as pessoas que conhecem os componentes internos do AngularJS me corrijam se eu estiver errado em algo.
Do not create new objects on every getEntities() call.
pode ser corrigido facilmente assim:<div ng-repeat="entity in entities = (entities || getEntities())">
getEntities()
sempre retornar a mesma matriz, se a matriz mudar, você não a obterá nong-repeat
Inicialize a matriz fora da repetição
fonte
getEntities()
retornar algo diferente no ciclo de vida do programa. Digamos, por exemplo, quegetEntities()
desencadeie um$http.get
. Quando get finalmente resolver (você fez a chamada AJAX),entities
já 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.
Isso foi relatado aqui e obteve esta resposta:
Você pode ver esse comportamento desaparecer se você mover a matriz para fora do controlador principal:
porque agora ele está retornando o mesmo objeto todas as vezes. Pode ser necessário refazer a arquitetura de seu modelo para usar uma propriedade no escopo em vez de uma função:
fonte
Com base no comentário de @przno
A segunda solução BTW @Artem Andreev sugere que não está funcionando no Angular 1.1.4 e superior, enquanto a primeira não resolve o problema. Portanto, por enquanto, esta é a solução menos pontiaguda, sem desvantagens na funcionalidade
fonte
Item.id
é o que deveria b. Obrigado