Passing variable to directive template without creating new scope

51,889

Solution 1

By default, directives do not create a new scope. If you want to make that explicit, add scope: false to your directive:

<div ng-click='back()' button='go back!'></div>
angular.module('myApp').directive("button", function () {
    return {
        scope: false,  // this is the default, so you could remove this line
        template: "<div><div another-directive></div>{{button}}</div>",
        replace: true,
        link: function (scope, element, attrs) {
           scope.button = attrs.button;
        }
    };
});

fiddle

Since a new property, button, is being created on the scope, you should normally create a new child scope using scope: true as @ardentum-c has in his answer. The new scope will prototypially inherit from the parent scope, which is why you don't need to put $parent.back() into your HTML.

One other tidbit to mention: even though we are using replace: true, clicking the element still calls back(). That works because "the replacement process migrates all of the attributes / classes from the old element to the new one." -- directive doc
So ng-click='back()' button='go back!' are migrated to the first div in the directive's template.

Solution 2

I guess you should use compile function in this case.

angular.module('myApp').directive("button", function () {
    return {
        template: "<div><div another-directive></div>{{button}}</div>",
        replace: true,
        scope:   true,
        compile: function (tElement, tAttrs) {
            // this is link function
            return function (scope) {
                scope.button = tAttrs.button;
            };            
        }
    };
});

Here is jsfiddle example.

Share:
51,889
Seb Fanals
Author by

Seb Fanals

Updated on July 19, 2022

Comments

  • Seb Fanals
    Seb Fanals almost 2 years

    Is there a way to pass variables using attributes to a directive without creating a new scope ?

    HTML

    <div ng-click='back()' button='go back'></div>
    

    JS

    .directive('button', function () {
        return {
            scope: {
                button: '@'
            },
            template: "<div><div another-directive></div>{{button}}</div>",
            replace: true
        }
    })
    

    The problem is that the ng-click='back()' now refers to the directive scope. I still can do ng-click='$parent.back()' but it's not what I want.