17

How do I set the interpolated value in a directive? I can read the correct value from the following code, but I have not been able to set it.

js:

app.directive('ngMyDirective', function () {
    return function(scope, element, attrs) {
        console.log(scope.$eval(attrs.ngMyDirective));

        //set the interpolated attrs.ngMyDirective value somehow!!!
    }
});

html:

<div ng-my-directive="myscopevalue"></div>

where myscopevalue is a value on my controller's scope.

2 Answers 2

45

Whenever a directive does not use an isolate scope and you specify a scope property using an attribute, and you want to change that property's value, I suggest using $parse. (I think the syntax is nicer than $eval's.)

app.directive('ngMyDirective', function ($parse) {
    return function(scope, element, attrs) {
        var model = $parse(attrs.ngMyDirective);
        console.log(model(scope));
        model.assign(scope,'Anton');
        console.log(model(scope));
    }
});

fiddle

$parse works whether or not the attribute contains a dot.

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

7 Comments

interesting stuff. thanks for the answer. You may have a point that parse may be a better term/syntax to use than eval. cheers
That's definitely the right way to implement '=' without scope isolation.
I had to add a scope.$apply() after the model.assign(...) in order to make the change of my directive reflected in the view. Is there any cleaner solution ?
Do you have a solution if the directive is inside a loop ? In such situation, this is always the first item which get updated.
This is a powerful technique and just what I was looking for. For instance, I wasn't able to find JSON assignment in the $eval space, but this solution works for that.
|
24

If you want to set a value on the scope but don't know the name of the property (ahead of time), you can use object[property] syntax:

scope[attrs.myNgDirective] = 'newValue';

If the string in the attribute contains a dot (e.g. myObject.myProperty), this won't work; you can use $eval to do an assignment:

// like calling  "myscopevalue = 'newValue'"
scope.$eval(attrs.myNgDirective + " = 'newValue'");

[Update: You should really use $parse instead of $eval. See Mark's answer.]

If you're using an isolate scope, you can use the = annotation:

app.directive('ngMyDirective', function () {
    return {
        scope: {
            theValue: '=ngMyDirective'
        },
        link: function(scope, element, attrs) {
            // will automatically change parent scope value
            // associated by the variable name given to `attrs.ngMyDirective`
            scope.theValue = 'newValue';
        }
    }
});

You can see an example of this in this Angular/jQuery color picker JSFiddle example, where assigning to scope.color inside the directive automatically updates the variable passed into the directive on the controller's scope.

8 Comments

scope[attrs.myNgDirective] = 'newValue'; worked! although the value of myNgDirective has to be directly on the scope, not a sub object of the scope. which makes sense
I believe you should be able to $eval with an assignment expression for object notation; I'll update my answer.
that would be cool. something like scope.$eval(attrs.ngMyDirective = 'new value') ?
excellent that is exactly what i need. i am upvoting in spirit now because the stack wont let me do it more than once
I prefer $parse over $eval. 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.