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?

Foi útil?

Solução

Há três mecanismos aqui envolvidos para que explica este comportamento:

  1. Os observadores são executados na mesma ordem que eles sejam registrados (veja o código do $watch método()).

  2. O pós-funções de ligação são executados na ordem inversa de prioridade (consulte a documentação para o priority propriedade).

  3. 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 o select directiva como também uma prioridade de 0, 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 que 0.
  • 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.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top