Accéder aux attributs depuis une directive AngularJS

95

Mon modèle AngularJS contient une syntaxe HTML personnalisée comme:

<su-label tooltip="{{field.su_documentation}}">{{field.su_name}}</su-label>

J'ai créé une directive pour le traiter:

.directive('suLabel', function() {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
      title: '@tooltip'
    },
    template: '<label><a href="#" rel="tooltip" title="{{title}}" data-placement="right" ng-transclude></a></label>',
    link: function(scope, element, attrs) {
      if (attrs.tooltip) {
        element.addClass('tooltip-title');
      }
    },
  }
})

Tout fonctionne correctement, à l'exception de l' attrs.tooltipexpression, qui revient toujours undefined, même si l' tooltipattribut est visible depuis la console JavaScript de Google Chrome lors de l'exécution d'un fichier console.log(attrs).

Toute suggestion?

MISE À JOUR: Une solution a été proposée par Artem. Cela consistait à faire ceci:

link: function(scope, element, attrs) {
  attrs.$observe('tooltip', function(value) {
    if (value) {
      element.addClass('tooltip-title');
    }
  });
}

AngularJS + stackoverflow = bonheur

Ismael Ghalimi
la source
Cette réponse à une autre question explique comment exprimer correctement un ternaire dans AngularJS.
Ismael Ghalimi
Donc très ceci: "AngularJS + stackoverflow = bliss"
twip

Réponses:

83

Voir la section Attributs de la documentation sur les directives.

observation des attributs interpolés : utilisez $ observe pour observer les changements de valeur des attributs qui contiennent une interpolation (par exemple src = "{{bar}}"). Non seulement cela est très efficace, mais c'est aussi le seul moyen d'obtenir facilement la valeur réelle car pendant la phase de liaison, l'interpolation n'a pas encore été évaluée et la valeur est donc à ce moment définie sur indéfinie.

Artem Andreev
la source
2
L'URL est maintenant changée en docs.angularjs.org/api/ng/service/$compile#Attributes
bhatiaravi
25

Bien que l'utilisation de '@' soit plus appropriée que d'utiliser '=' pour votre scénario particulier, j'utilise parfois '=' pour ne pas avoir à me souvenir d'utiliser attrs. $ Observe ():

<su-label tooltip="field.su_documentation">{{field.su_name}}</su-label>

Directif:

myApp.directive('suLabel', function() {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: {
            title: '=tooltip'
        },
        template: '<label><a href="#" rel="tooltip" title="{{title}}" data-placement="right" ng-transclude></a></label>',
        link: function(scope, element, attrs) {
            if (scope.title) {
                element.addClass('tooltip-title');
            }
        },
    }
});

Violon .

Avec '=', nous obtenons une liaison de données bidirectionnelle, il faut donc veiller à ce que scope.title ne soit pas accidentellement modifié dans la directive. L'avantage est que pendant la phase de liaison, la propriété de portée locale (scope.title) est définie.

Mark Rajcok
la source
Hé Mark, quelle est votre opinion sur l'utilisation de ces solutions, existe-t-il une directive spécifique pour l'utilisation d'observer sur le lien attrs contre l'utilisation de la liaison de données bidirectionnelle? Je pense qu'il semble plus propre d'utiliser la liaison de données bidirectionnelle, mais je me demande s'il y a une raison de ne pas l'utiliser.
Jeroen
@Jeroen, j'ai posté une discussion plus longue sur l'utilisation de @vs = ici .
Mark Rajcok