Доступ к атрибутам из директивы AngularJS

95

Мой шаблон AngularJS содержит настраиваемый синтаксис HTML, например:

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

Я создал директиву для его обработки:

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

Все работает нормально, за исключением attrs.tooltipвыражения, которое всегда возвращается undefined, даже если tooltipатрибут виден из консоли JavaScript Google Chrome при выполнении console.log(attrs).

Любое предложение?

ОБНОВЛЕНИЕ: Решение предложил Артем. Он заключался в следующем:

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

AngularJS + stackoverflow = блаженство

Исмаэль Галими
источник
Этот ответ на другой вопрос объясняет, как правильно выразить тернар в AngularJS.
Исмаэль Галими
Вот так: «AngularJS + stackoverflow = bliss»
twip

Ответы:

83

См. Раздел Атрибуты документации по директивам.

наблюдение за интерполированными атрибутами : используйте $ наблюдение, чтобы наблюдать за изменениями значений атрибутов, содержащих интерполяцию (например, src = "{{bar}}"). Это не только очень эффективно, но и единственный способ легко получить фактическое значение, потому что на этапе связывания интерполяция еще не была оценена, и поэтому значение в настоящее время установлено на undefined.

Артем Андреев
источник
2
URL-адрес теперь изменен на docs.angularjs.org/api/ng/service/$compile#Attributes
bhatiaravi
25

Хотя использование '@' более уместно, чем использование '=' для вашего конкретного сценария, иногда я использую '=', чтобы мне не нужно было помнить об использовании attrs. $ Наблюдать ():

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

Директива:

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

Скрипка .

С '=' мы получаем двустороннюю привязку данных, поэтому необходимо позаботиться о том, чтобы в директиве не было случайно изменено scope.title. Преимущество заключается в том, что на этапе связывания определяется свойство локальной области (scope.title).

Марк Райкок
источник
Привет, Марк, каково ваше мнение об использовании этих решений, есть ли конкретное руководство по использованию наблюдения в атрибутах ссылок вместо использования двусторонней привязки данных? Я думаю, что использование двусторонней привязки данных выглядит чище, но мне интересно, есть ли причина не использовать ее?
Jeroen
@Jeroen, я опубликовал более подробное обсуждение использования @vs = здесь .
Марк Райкок