Modelo de diretiva de cenário simples Ng-Repeat (sem repetição)Url
-
21-12-2019 - |
Pergunta
Fechamento com diretiva simples
Eu tenho um fechamento simples que possui algumas propriedades, olá e itens.Quando ligo, o hello world funciona bem, mas a lista não é renderizada quando uso o ng-repeat.
(function() {
var app = angular.module('safety-plus-task-list', []);
app.directive('taskList', function () {
return {
restrict: "E",
templateUrl: "/Task/TaskList",
scope: {
},
controller: function ($http, $scope, $element, $attrs) {
this.hello = "HELLO WORLD";
this.items = [
"gravida nisl, id fringilla neque ante vel mi.",
"quam gravida nisl, id fringilla neque ante vel mi."];
},
controllerAs: "task"
};
});
})();
Diretiva interna do código
Aqui está o código usado para renderizar a diretiva personalizada.A variável hello aparece corretamente, mas os itens não são renderizados.Se houver um item na lista, ele aparecerá.
{{ task.hello }}
<div ng-repeat="item in task.items">
<div> {{ item }} </div>
</div>
Imagem renderizada
Cordas idênticas quebram o loop
Este parece ser um comportamento não intuitivo.Tente você mesmo.Alterei uma letra do meu exemplo e o modelo foi renderizado conforme o esperado.
Alguém pode me dizer por que isso se comporta assim?
Exemplo do código.Este código produz resultados diferentes e não funciona por algum motivo, a menos que você adicione o prefixo "$scope" em vez de "this" como em insira a descrição do link aqui.Para tornar as coisas mais confusas, a versão com escopo definido, na verdade, não produz o problema que esta postagem descreve.
Solução
ngRepeat
espera items
serem objetos diferentes (comparando por ===
).
Como as strings são primitivas, 2 strings iguais são consideradas iguais/idênticas.
Você pode usar track by
para instruir ngRepeat
para comparar outra coisa, por ex.índices:
ng-repeat="item in task.items track by $index"
Outras dicas
Veja como ngRepeat
é implementado:
//...at line 225
if (trackByExp) {
trackByExpGetter = $parse(trackByExp);
trackByIdExpFn = function(key, value, index) {
// assign key, value, and $index to the locals so that they can be used in
hash functions
if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
hashFnLocals[valueIdentifier] = value;
hashFnLocals.$index = index;
return trackByExpGetter($scope, hashFnLocals);
};
} else {
trackByIdArrayFn = function(key, value) {
return hashKey(value);
};
}
//...at line 289
trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
ngRepeat
rastreia elementos por uma função id, que pode ser fornecida pelo track by
expressão (trackByIdExpFn
), ou é decidido pela própria directiva (trackByIdArrayFn
).Neste caso, como você pode ver, a expressão é simplesmente return hashKey(value)
.Isso significa que você tem uma colisão para elementos idênticos.