How to modify scope from within a directive in AngularJs
Solution 1
I updated the fiddle, basically had to go to the parent to get the right "selected" variable, also used the isolate scope = to get two way binding between the value passed in and the internal model.
angular.module('app', [])
.directive("customTag", [function () {
return {
restrict: "E",
replace: true,
template: "<input type='button' value='Click me' />",
scope: {model:'='},
link: function (scope, element, attrs) {
element.bind('click', function () {
scope.model[attrs.selectedItem] = "New value";
scope.$apply();
});
}
};
}]);
function AppController($scope) {
$scope.selected = 'Old value';
}
and the HTML
<div ng-app="app" ng-controller='AppController'>
<p>Selected: {{ selected }}</p>
<div ng-switch on="selected">
<div ng-switch-default>
<p>Item: {{ selected }}</p>
<custom-tag selected-item="selected" model="$parent" />
</div>
<div ng-switch-when="New value">
<p>Worked</p>
</div>
</div>
</div>
Updated the fiddle to use your original reading of the property from the attribute: http://jsfiddle.net/nJ7FQ/4/
Solution 2
I improved the jsfiddle a bit:
angular.module('app', [])
.directive("customTag", ['$parse', function ($parse) {
return {
restrict: "E",
replace: true,
template: "<input type='button' value='Click me' />",
link: function (scope, element, attrs) {
element.bind('click', function () {
scope.$apply(function () {
$parse(attrs.selectedItem).assign(scope.$parent, "New value");
});
});
}
};
}]);
function AppController($scope) {
$scope.selected = { 'foo': 'Old value' };
}
This way, the scope value, you want to change can also be an object property like selected.foo
in the example. Also, I removed the scope parameter and told the directive to always use the parent scope. And finally I wrapped the click handler into the $apply
callback (see here for example). Better would be, of course, to use ngClick
instead of the element.bind()
.
Related videos on Youtube
Fernando
Updated on July 09, 2022Comments
-
Fernando almost 2 years
I need to modify a root scope attribute from within a callback inside a directive. But the directive is in a inner scope created by a switch directive.
HTML
<div ng-app="app" ng-controller='AppController'> <p>Selected: {{ selected }}</p> <div ng-switch on="selected"> <div ng-switch-default> <p>Item: {{ selected }}</p> <custom-tag selected-item="selected" /> </div> <div ng-switch-when="New value"> <p>Worked</p> </div> </div> </div>
JavaScript
angular.module('app', []) .directive("customTag", [function () { return { restrict: "E", replace: true, template: "<input type='button' value='Click me' />", link: function (scope, element, attrs) { element.bind('click', function () { scope[attrs.selectedItem] = "New value"; scope.$apply(); }); } }; }]); function AppController($scope) { $scope.selected = 'Old value'; }
Fiddle: http://jsfiddle.net/nJ7FQ/
My objective is to be able to display "New value" in the Selected area. How can I accomplish what I am trying to do? What am I doing wrong?
Besides, as I am trying to make a component. Is there a way to do the same but with an isolated scope?
-
Fernando almost 11 yearsI liked better your first solution (jsfiddle.net/nJ7FQ/2) It seems cleaner somehow. But why should I use $parent.selected when, from what I understand, child scopes inherits all the properties of the parent?
-
shaunhusain almost 11 yearsWell if you change the selected for the one that was inherited it doesn't change the parent scopes selected variable, by going up to the parent and changing the variable on that scope then when the child selected value is read it goes up to the parent. If you change the child scope's selected property it would become a new property on the child scope and no longer inherit. (I know it's confusing) This is Javascript prototypical inheritence if you want to Google it.
-
dopatraman over 9 yearsThis does not work. setting
scope:'='
in the directive makesscope
undefined. -
shaunhusain over 9 years@dopatraman, yeah having learned more about angular in the last year, I wouldn't agree with my own answer here, that said I'm not sure that the issue you're encountering is related to the problems I would have with this method. If you posted another SO question with your code and problem link it here and I'll take a look.
-
saike over 8 yearsBINGO! Good solution to assign parent scope. Ideal for something like modals
-
The Red Pea over 7 yearsNote that
link
must be used; this alternative, exactly the same as shaunhusain's, except for usingcontroller
, doesn't work. Presumably it's because isolate scope is only set up in time for thelink
function, not thecontroller
function.