28

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.

2
  • you should be using &attr to call parent functions passed as attribute stackoverflow.com/questions/15991137/… Commented May 15, 2013 at 9:40
  • I would like have a generic way. Not scope: {back: '&'} if it's what you mean ? To be able to do: <div ng-click='start_game()' button='Start'></div> for another example. Commented May 15, 2013 at 10:08

2 Answers 2

34

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.

Sign up to request clarification or add additional context in comments.

2 Comments

You're right but I need the isolated scope to have multiple buttons with different names. Bad formulated question I guess. jsfiddle.net/gHjU4/2
OK now I'm feeling dumb, as you said, scope:true and no compile needed. I changed the accepted answer.
3

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.

2 Comments

I never used compile before but I saw it in the docs, should of read it. Thanks !
scope: true creates a new scope. While I think this is the correct way to do it, the OP asked for no new scope. Also, a compile function is not necessary, only a link function. See my answer for more info.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.