简体   繁体   中英

AngularJS : can not change parent scope via directive

I am trying to change the controllers scope via directive but it does not change.

The goas is to change the $scope.modules in MyCtrl automaticly when i am changing model via directive:

link: function (scope) {
    scope.module.title += ' changed';

    scope.module = {
        title: 'Redeclared'
    };
},

This code works perfectly scope.module.title += ' changed';

But this not: scope.module = { title: 'Redeclared' };

After $http.get request we have an object with {title: 'Redeclared'} thats why i am doing so scope.module = { title: 'Redeclared' };

Example: http://jsfiddle.net/8Va9Q/

Any idea how to do this? Thanks

Your problem is due to scope / prototype inheritance.

When you set the 'module' variable to a new reference, your new variable will be known in your current scope only. On the parent scope, the 'module' variable remained untouched.

You can see the final result such as:

-> parent scope
   -> module = { title: 'foo' }
   -> child scope
       -> module = { title: 'Redeclared' }

Instead, if you only set the title attribute of your 'module' variable, then the attribute (on the 'module' variable) on the parent scope will be updated.

If you want to override the variable, use angular.extend (it will override your object attributes) :

angular.extend($scope.module, {
    title: 'Redeclared'
});

Your fiddle is up to date.

There is a really good answer about scope inheritance with AngularJS on SO here: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

This is the perfect answer, and you should definitely read this.

Assuming $rootScope.module === directiveScope.module

Then this "problem" is because you de reference scope.module instead of mutating it:

var original = {name:"original"} ;
var copy = original;// copy is a reference to original (copy === original)
copy.name="copy";//mutating copy changes original
console.log(original.name);//=copy
//re assigning copy de references original
//copy no longer has a reference to original
//and carries it's own value
copy={name:"changed"};
console.log(original.name);//=copy (not changed)

A common mistake when passing object variables, sometimes you want to mutate them but re assign them and thereby de reference them and sometimes you don't want to change them but accidentally do by mutating them (someArray.sort() or someArray.push("new Item") or someObject.newItem=88 ...).

angular.extend does not re assign scope.module or $rootScope.module, the following:

angular.extend(scope.module, {
    title: 'Redeclared'
});

Is the same as but slower than:

scope.module.title="Redeclared";

If rootScope.module was {somevar:22} then both code examples would end up with {somevar:22,title:"Redeclared"} It could be used for a situation where you have to mutate scope.module with a received json object:

scope.module.prop1 = receivedJSON.prop1;
scope.module.prop2 = receivedJSON.prop2;
//...many more
scope.module.prop100 = receivedJSON.prop100;

Would be a lot shorter with:

angular.extend(scope.module, receivedJSON);

it's all about JavaScript data types: here you change option of object that is provided by link (scope.module)

scope.module.title 

and here you totally rewrite the whole object (no link)

scope.module

So for you case it's better to do: not

   $scope.modules = [{
        title: 'test 0'
    }, {
        title: 'test 1'
    }, {
        title: 'test 2'
    }];

but

$scope.modules.push(title: 'test 0'})
$scope.modules.push(title: 'test 1'})
$scope.modules.push(title: 'test 2'})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM