Как передать несколько атрибутов в директиву атрибутов Angular.js?

116

У меня есть директива атрибута, ограниченная следующим образом:

 restrict: "A"

Мне нужно передать два атрибута; число и функция / обратный вызов, доступ к ним в директиве с помощью attrsобъекта.

Если бы эта директива была директивой элемента, "E"я мог бы ограничиться этим:

<example-directive example-number="99" example-function="exampleCallback()">

Однако по причинам, которые я не буду вдаваться в подробности, мне нужно, чтобы директива была директивой атрибута.

Как передать несколько атрибутов в директиву атрибутов?

Undistraction
источник
Это зависит от типа области, которую создает ваша директива (если таковая имеется). Возможны следующие варианты: отсутствие новой области (по умолчанию или явная с scope: false), новая область (с обычным прототипным наследованием, т. Е. scope: true) И изолированная область (т. Е. scope: { ... }). Какую область видимости создает ваша директива?
Марк Райкок
1
@MarkRajcok Он имеет изолированную область.
Undistraction

Ответы:

202

Директива может обращаться к любому атрибуту, который определен для того же элемента, даже если сама директива не является элементом.

Шаблон:

<div example-directive example-number="99" example-function="exampleCallback()"></div>

Директива:

app.directive('exampleDirective ', function () {
    return {
        restrict: 'A',   // 'A' is the default, so you could remove this line
        scope: {
            callback : '&exampleFunction',
        },
        link: function (scope, element, attrs) {
            var num = scope.$eval(attrs.exampleNumber);
            console.log('number=',num);
            scope.callback();  // calls exampleCallback()
        }
    };
});

fiddle

Если значение атрибута example-numberбудет жестко запрограммировано, я предлагаю использовать $evalодин раз и сохранить значение. Переменная numбудет иметь правильный тип (число).

Марк Райкок
источник
Я отредактировал пример HTML, чтобы использовать snake-case. Я знаю, что не могу использовать его как элемент. В этом суть вопроса.
Undistraction
@Pedr, да, извини, я слишком быстро прочитал об использовании элемента. Я обновил ответ, отметив, что вам также нужно использовать snake-case для атрибутов.
Марк Райкок
Нет проблем. Спасибо за Ваш ответ. Я отредактировал имена атрибутов, чтобы использовать snake-case. Хорошо, если я уберу это из вашего ответа, так как это была просто моя глупая ошибка и отвлекает от сути вопроса и ответа?
Undistraction
Я не понимаю - откуда директива узнает, что в ее области действия указано то же самое, что указано в использовании директивы ("exampleCallback ()")? ("callback: '& exampleCallback') Разве область видимости не должна быть" callback: "& exampleFunction"?
Blaster
1
@FredrikL, несколько директив для одного и того же элемента см. На stackoverflow.com/a/28735005/215945
Марк Райкок
19

Вы делаете это точно так же, как и с директивой element. Они будут у вас в объекте attrs, в моем примере есть двусторонняя привязка через область выделения, но это не обязательно. Если вы используете изолированную область видимости, вы можете получить доступ к атрибутам с помощью scope.$eval(attrs.sample)или просто scope.sample, но они могут не определяться при связывании в зависимости от вашей ситуации.

app.directive('sample', function () {
    return {
        restrict: 'A',
        scope: {
            'sample' : '=',
            'another' : '='
        },
        link: function (scope, element, attrs) {
            console.log(attrs);
            scope.$watch('sample', function (newVal) {
                console.log('sample', newVal);
            });
            scope.$watch('another', function (newVal) {
                console.log('another', newVal);
            });
        }
    };
});

используется в качестве:

<input type="text" ng-model="name" placeholder="Enter a name here">
<input type="text" ng-model="something" placeholder="Enter something here">
<div sample="name" another="something"></div>
Джонатан Роуни
источник
9

Вы можете передать объект как атрибут и прочитать его в директиве следующим образом:

<div my-directive="{id:123,name:'teo',salary:1000,color:red}"></div>

app.directive('myDirective', function () {
    return {            
        link: function (scope, element, attrs) {
           //convert the attributes to object and get its properties
           var attributes = scope.$eval(attrs.myDirective);       
           console.log('id:'+attributes.id);
           console.log('id:'+attributes.name);
        }
    };
});
Тео Ицарис
источник
Можно ли отправить логическое значение с помощью объекта? Я пробовал, {{true}}но он по-прежнему возвращает строковое значение true.
Питер
4

Это сработало для меня, и я думаю, что он более совместим с HTML5. Вы должны изменить свой html, чтобы использовать префикс data-

<div data-example-directive data-number="99"></div>

И в директиве прочитайте значение переменной:

scope: {
        number : "=",
        ....
    },
jmontenegro
источник
0

Если вам «требуется» exampleDirective из другой директивы + ваша логика находится в контроллере exampleDirective (скажем, exampleCtrl):

app.directive('exampleDirective', function () {
    return {
        restrict: 'A',
        scope: false,
        bindToController: {
            myCallback: '&exampleFunction'
        },
        controller: 'exampleCtrl',
        controllerAs: 'vm'
    };
});
app.controller('exampleCtrl', function () {
    var vm = this;
    vm.myCallback();
});
Кот Илькер
источник