Вопрос

У меня очень специфическая проблема с директивой, начинающейся с определенных букв (t, u, v, w, y, z).Директива используется на select элемент и следит за ngOptions изменения.

Когда ngOptions заполняется данными из Ajax-запроса, а имя директивы начинается с определенной буквы, напримерw, второй обратный вызов Watch срабатывает до того, как будут созданы параметры выбора.Если имя директивы начинается с другой буквы (a, k, m, n), второй обратный вызов отслеживания срабатывает после создания параметров.

Вот образец с несколькими директивами, начинающимися с разных букв.Откройте консоль, чтобы увидеть проблему.

<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());
            });
        }
    };
});

В приведенном выше коде element.html() будет содержать один пустой option в первом обратном вызове просмотра (начальный дайджест), а также будет содержать один пустой option во втором дайджесте (когда Ajax будет завершен).

Откуда такое поведение?

Это было полезно?

Решение

Здесь есть три механизма, которые объясняют такое поведение:

  1. Наблюдателей казнят в тот же порядок что они зарегистрированы(посмотреть код $watch метод()).

  2. Функции постлинка выполняются в обратный порядок своего приоритета (см. документацию по priority свойство).

  3. Директивы с одинаковым приоритетом выполняются в неопределенном порядке.Приоритет по умолчанию 0, поэтому все ваши пользовательские директивы имеют этот приоритет.Поскольку select директива, а также приоритет 0, порядок выполнения не определен.

    Как вы заметили, слово «неопределено» немного избыточно, и на самом деле порядок выполнения такой же. Алфавитный порядок (увидеть $compile код):директивы с именем в начале словаря имеют более высокий приоритет.Но, по моему скромному мнению, поскольку в документации об этом прямо не сказано, ты не можешь полагаться на такое поведение.

Подводя итог, приведем несколько вариантов использования.Каждая директива регистрирует наблюдателя.

  Name  |  Priority  | Watcher order
--------+------------+--------------
A       | 100        | 3rd
B       | 0          | 2nd
C       | none (= 0) | 1st

Таким образом, исправить проблему просто:

  • Если вы хотите выполнить наблюдатель ваших пользовательских директив после тот select один, просто дайте вашей директиве приоритет выше, чем 0.
  • Если вы хотите выполнить наблюдатель ваших пользовательских директив до тот select один, ну… поскольку отрицательный приоритет запрещен, вы не можете сделать это надежно.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top