Accediendo a atributos desde una directiva AngularJS

95

Mi plantilla AngularJS contiene alguna sintaxis HTML personalizada como:

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

Creé una directiva para procesarlo:

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

Todo funciona bien, a excepción de la attrs.tooltipexpresión, que siempre regresa undefined, aunque el tooltipatributo es visible desde la consola JavaScript de Google Chrome al hacer un console.log(attrs).

¿Cualquier sugerencia?

ACTUALIZACIÓN: Artem ofreció una solución. Consistió en hacer esto:

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

AngularJS + stackoverflow = felicidad

Ismael Ghalimi
fuente
Esta respuesta a otra pregunta explica cómo expresar correctamente un ternario en AngularJS.
Ismael Ghalimi
Muy bien esto: "AngularJS + stackoverflow = bliss"
twip

Respuestas:

83

Consulte la sección Atributos de la documentación sobre directivas.

observando atributos interpolados : Use $ observe para observar los cambios de valor de los atributos que contienen interpolación (por ejemplo, src = "{{bar}}"). Esto no solo es muy eficiente, sino que también es la única forma de obtener fácilmente el valor real porque durante la fase de vinculación, la interpolación aún no se ha evaluado y, por lo tanto, el valor en este momento se establece en indefinido.

Artem Andreev
fuente
2
La URL ahora se cambió a docs.angularjs.org/api/ng/service/$compile#Attributes
bhatiaravi
25

Aunque usar '@' es más apropiado que usar '=' para su escenario particular, a veces uso '=' para no tener que recordar usar attrs. $ Observe ():

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

Directiva:

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

Violín .

Con '=' obtenemos un enlace de datos bidireccional, por lo que se debe tener cuidado para garantizar que scope.title no se modifique accidentalmente en la directiva. La ventaja es que durante la fase de vinculación, se define la propiedad del alcance local (scope.title).

Mark Rajcok
fuente
Hola Mark, ¿cuál es su opinión sobre el uso de estas soluciones? ¿Existe una pauta específica para usar observe en los atributos de enlace en contra del uso de la vinculación de datos bidireccional? Creo que parece más limpio usar el enlace de datos bidireccional, pero me pregunto si hay alguna razón para no usarlo.
Jeroen
@Jeroen, publiqué una discusión más larga sobre el uso de @vs = aquí .
Mark Rajcok