Válido directiva nomes
-
21-12-2019 - |
Pergunta
Eu tenho um problema muito específico, com uma directiva início com certas letras (a, t, u, v, w, y, z).A diretiva é usada em um select
elemento e olha para ngOptions
alterações.
Quando ngOptions
é preenchido com dados de uma solicitação Ajax, e a directiva nome começa com uma determinada letra, por exemplo,w, o segundo relógio de retorno de chamada é acionado antes de selecionar opções foram criadas.Se a directiva nome começa com uma letra diferente (a, k, m, n) o segundo relógio de retorno de chamada é acionado depois que as opções foram criadas.
Aqui está um exemplo de com várias directivas começando com várias letras.Abra o seu console para ver o problema.
<select w-foo ng-model="bar" ng-options="o.name for o in options"></select>
app.controller("test", function ($scope, $timeout) {
// Emulate ajaxed options
$timeout(function () {
$scope.options = [{
name: "aaa",
id: 1
}, {
name: "bbb",
id: 2
}, {
name: "ccc",
id: 3
}];
}, 500);
});
app.directive("wFoo", function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngOptions.replace(/.*in /, ""), function () {
console.log("w-foo ngOptions changed", element.html());
});
}
};
});
No código acima, element.html()
irá conter um único vazio option
o primeiro relógio de retorno de chamada (inicial digest) e também irá conter um único vazio option
no segundo digest (quando o Ajax é completa).
Onde é que esse comportamento vem?
Solução
Há três mecanismos aqui envolvidos para que explica este comportamento:
Os observadores são executados na mesma ordem que eles sejam registrados (veja o código do
$watch
método()).O pós-funções de ligação são executados na ordem inversa de prioridade (consulte a documentação para o
priority
propriedade).Directivas com a mesma prioridade são executadas em uma ordem indefinida.A prioridade padrão é
0
, para que todos os seus personalizado directivas aqui tem essa prioridade.Desde oselect
directiva como também uma prioridade de0
, a ordem de execução é indefinido.Como você percebe, "indefinido" é um pouco excessiva, e na verdade, a ordem de execução é o por ordem alfabética (ver o
$compile
código):directivas com um nome no início do dicionário, têm uma maior prioridade.Mas, na minha humilde opinião, desde que esse não seja explicitamente dito na documentação, você não pode contar com esse comportamento.
Para resumir, aqui está alguns casos de uso.Cada directiva registra um observador.
Name | Priority | Watcher order
--------+------------+--------------
A | 100 | 3rd
B | 0 | 2nd
C | none (= 0) | 1st
Assim, para resolver o problema é simples:
- Se você deseja executar o observador de seu personalizado directivas depois de o
select
uma, basta dar ao seu directiva uma prioridade maior do que0
. - Se você deseja executar o observador de seu personalizado directivas antes de o
select
um, bem... desde negativo prioridade é proibido, você não pode de maneira confiável de fazer isso.