How do I pass multiple attributes into an Angular.js attribute directive?

119,595

Solution 1

The directive can access any attribute that is defined on the same element, even if the directive itself is not the element.

Template:

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

Directive:

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

If the value of attribute example-number will be hard-coded, I suggest using $eval once, and storing the value. Variable num will have the correct type (a number).

Solution 2

You do it exactly the same way as you would with an element directive. You will have them in the attrs object, my sample has them two-way binding via the isolate scope but that's not required. If you're using an isolated scope you can access the attributes with scope.$eval(attrs.sample) or simply scope.sample, but they may not be defined at linking depending on your situation.

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

used as:

<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>

Solution 3

You could pass an object as attribute and read it into the directive like this:

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

Solution 4

This worked for me and I think is more HTML5 compliant. You should change your html to use 'data-' prefix

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

And within the directive read the variable's value:

scope: {
        number : "=",
        ....
    },
Share:
119,595

Related videos on Youtube

Undistraction
Author by

Undistraction

Updated on March 17, 2020

Comments

  • Undistraction
    Undistraction over 4 years

    I have an attribute directive restricted as follows:

     restrict: "A"
    

    I need to pass in two attributes; a number and a function/callback, accessing them within the directive using the attrs object.

    If the directive was an element directive, restricted with "E" I could to this:

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

    However, for reasons I won't go into I need the directive to be an attribute directive.

    How do I pass multiple attributes into an attribute directive?

    • Mark Rajcok
      Mark Rajcok about 11 years
      That depends on the type of scope your directive creates (if any). Choices are: no new scope (default, or explicit with scope: false), new scope (with normal prototypal inheritance, i.e., scope: true), and isolate scope (i.e., scope: { ... }). What type of scope does your directive create?
    • Undistraction
      Undistraction about 11 years
      @MarkRajcok It has an isolate scope.
  • Undistraction
    Undistraction about 11 years
    I've edited the example HTML to use snake-case. I know I can't use it as an element. That's the point of the question.
  • Mark Rajcok
    Mark Rajcok about 11 years
    @Pedr, yeah, sorry I read too fast about the element usage. I updated the answer, noting that you also need to use snake-case for the attributes too.
  • Undistraction
    Undistraction about 11 years
    No problem. Thanks for your answer. I've edited the attribute names to use snake-case. You OK if I remove that from your answer as it was just a silly error by me and distracts from the point of the actual question and answer?
  • blaster
    blaster almost 11 years
    I don't get this - how does the directive know to name the exact same thing specified in the directive usage ("exampleCallback()") in its scope? ("callback : '&exampleCallback') Shouldn't the scope be "callback : "&exampleFunction" ?
  • Mark Rajcok
    Mark Rajcok almost 11 years
    @blaster, yes thanks for the correction. I updated the answer.
  • Fredrik L
    Fredrik L about 9 years
    Does this work even if there are multiple directives on the same element?
  • Mark Rajcok
    Mark Rajcok about 9 years
    @FredrikL, for multiple directives on the same element, please see stackoverflow.com/a/28735005/215945
  • James Drinkard
    James Drinkard over 7 years
    I had this same requirement, except I had to pass in a string array of values. This code gave me the starting point to get it working! Thanks Mark!
  • Somnium
    Somnium over 7 years
    How can I get exampleNumber in controller (updated value, not that which was at the time of creating directive) without defining it in scope parameters?
  • Peter Boomsma
    Peter Boomsma over 4 years
    Is it possible to send a boolean value using a object? I tried {{true}} but it still returns the string value true.