Question

J'ai un problème très spécifique avec une directive commençant par certaines lettres (t, u, v, w, y, z).La directive est utilisée sur un select élément et surveille ngOptions changements.

Quand ngOptions est rempli avec les données d'une requête Ajax et le nom de la directive commence par une certaine lettre, par ex.w, le deuxième rappel de surveillance se déclenche avant que les options de sélection n'aient été créées.Si le nom de la directive commence par une lettre différente (a, k, m, n), le deuxième rappel de surveillance se déclenche une fois les options créées.

Voici un échantillon avec plusieurs directives commençant par différentes lettres.Ouvrez votre console pour voir le problème.

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

Dans le code ci-dessus, element.html() contiendra un seul vide option dans le premier rappel de surveillance (le résumé initial) et contiendra également un seul vide option dans le deuxième résumé (lorsque l'Ajax est terminé).

D'où vient ce comportement ?

Était-ce utile?

La solution

Il y a ici trois mécanismes qui sont impliqués pour expliquer ce comportement :

  1. Les observateurs sont exécutés dans le même ordre qu'ils sont enregistrés (voir le code du $watch méthode()).

  2. Les fonctions post-lien sont exécutées dans le ordre inverse de leur priorité (voir la documentation du priority propriété).

  3. Les directives avec la même priorité sont exécutées dans un ordre indéfini.La priorité par défaut est 0, donc toutes vos directives personnalisées ici ont cette priorité.Depuis le select directive comme également une priorité de 0, l'ordre d'exécution n'est pas défini.

    Comme vous le remarquez, "undefined" est un peu excessif, et en réalité l'ordre d'exécution est le ordre alphabétique (voir le $compile code) :les directives avec un nom au début du dictionnaire ont une priorité plus élevée.Mais, à mon humble avis, puisque cela n'est pas explicitement dit dans la documentation, tu ne peux pas compter sur ce comportement.

Pour résumer, voici quelques cas d'utilisation.Chaque directive enregistre un observateur.

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

Ainsi, pour résoudre le problème, c'est simple :

  • Si vous souhaitez exécuter le watcher de vos directives personnalisées après le select un, donnez simplement à votre directive une priorité supérieure à 0.
  • Si vous souhaitez exécuter le watcher de vos directives personnalisées avant le select un, eh bien… puisque les priorités négatives sont interdites, vous ne pouvez pas le faire de manière fiable.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top