Ben
Ben

Reputation: 62384

How to modify a scope's value within a directive

Within a directive, I'd like to modify the expression's value when a button is clicked. The below code is only modifying the value locally within my directive. I'd like to change the value outside of this directive as well. How can I accomplish that?

        scope: false,
        link: function (scope, el, attrs) {
            //toggle the state when clicked
            el.bind('click', function () {
                scope[attrs.ngModel] = !scope[attrs.ngModel];
            });

Plunker: http://plnkr.co/edit/xqYBnz5BHLP844kXJXKs?p=preview

Upvotes: 0

Views: 1104

Answers (3)

zs2020
zs2020

Reputation: 54514

Since you are not creating a new scope, then you should be able to access the model via scope not attrs

In the directive, change the scope to

scope: {
    ngModel: '='
},

And change the scope.$apply to

scope.$apply(function () {
    if (scope.ngModel) {
        off();
        scope.ngModel = false;
    } else {
        on();
        scope.ngModel = true;
    }
});

DEMO

Upvotes: 0

Chandermani
Chandermani

Reputation: 42669

The problems is with the binding expression in ng-model. Since it has '.' in it, you need to use the $parse to get and set value correctly. See some documentation here

Something like

 var getter=$parse(attrs.ngModel);
 var setter=getter.assign;
 setter(scope,!getter(scope));

See my updated plunkr here http://plnkr.co/edit/VAE43y5cagCF8jq5AlaY?p=preview

Basically setting

scope[attrs.ngModel] = !scope[attrs.ngModel]

creates a new property user.active. To set it should be scope['user']['active'];

Upvotes: 4

thalisk
thalisk

Reputation: 7743

An alternative way would be to create an isolate scope and pass in your directive an attribute that will link it to a method in the parent scope which will do the work of flipping the state.

Rough example:

In your directive definition:

scope: {
    flipState: '&'
},
link: function (scope, elem, attr) {
    elem.bind('click', function () {
        flipState();
    }
}

In your view:

<div ng-controller="MyController">
    /* ... */
    <button directivename flip-state="flipStateFunc()"></button>
</div>

And in your controller MyController:

flipStateFunc: function () {
    $scope.state = !$scope.state;
}

Upvotes: 0

Related Questions