Acessando atributos de uma diretiva AngularJS

95

Meu modelo AngularJS contém alguma sintaxe HTML personalizada como:

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

Eu criei uma diretiva para processá-lo:

.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');
      }
    },
  }
})

Tudo funciona bem, exceto a attrs.tooltipexpressão, que sempre retorna undefined, embora o tooltipatributo seja visível no console JavaScript do Google Chrome ao fazer um console.log(attrs).

Alguma sugestão?

ATUALIZAÇÃO: Uma solução foi oferecida pela Artem. Consistia em fazer isso:

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

AngularJS + stackoverflow = êxtase

Ismael Ghalimi
fonte
Esta resposta a outra pergunta explica como expressar adequadamente um ternário em AngularJS.
Ismael Ghalimi
Tão bem isto: "AngularJS + stackoverflow = bliss"
twip de

Respostas:

83

Consulte a seção Atributos da documentação sobre diretivas.

observando atributos interpolados : Use $ observe para observar as mudanças de valor dos atributos que contêm interpolação (por exemplo, src = "{{bar}}"). Isso não é apenas muito eficiente, mas também é a única maneira de obter facilmente o valor real, porque durante a fase de vinculação a interpolação ainda não foi avaliada e, portanto, o valor neste momento está definido como indefinido.

Artem Andreev
fonte
2
URL agora foi alterado para docs.angularjs.org/api/ng/service/$compile#Attributes
bhatiaravi
25

Embora usar '@' seja mais apropriado do que usar '=' para seu cenário particular, às vezes eu uso '=' para não ter que me lembrar de usar attrs. $ Observe ():

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

Diretriz:

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');
            }
        },
    }
});

Fiddle .

Com '=', obtemos ligação de dados bidirecional, portanto, deve-se tomar cuidado para garantir que scope.title não seja modificado acidentalmente na diretiva. A vantagem é que durante a fase de vinculação, a propriedade de escopo local (scope.title) é definida.

Mark Rajcok
fonte
Ei, Mark, qual é a sua opinião sobre o uso dessas soluções, há uma orientação específica para usar observe no atributo do link contra o uso de databinding bidirecional? Acho que parece mais limpo usar a ligação de dados bidirecional, mas será que há uma razão para não usá-la?
Jeroen
@Jeroen, postei uma discussão mais longa sobre o uso de @vs = aqui .
Mark Rajcok