34

I have a need for inheriting scope from a parent controller in a directive. I don't necessarily want to leave scope: false. I also don't necessarily want to use an isolated scope, because it requires a lot of work to get the values I do care about linked properly (think lots of values in a parent controller).

Does it make sense to use scope:true in my directive if I want to update parent scope?

<div ng-controller="MyCtrl">
      Hello, {{name}}!
        <my-directive></my-directive>
</div>
var myApp = angular.module('myApp',[]);

//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
    $scope.name = 'Dave';
}


myApp.directive('myDirective', function() {
    return {
        scope: true,
        restrict: 'EA',
        link: function(scope, elem, attrs) {
            scope.updateName = function(newName) {
                console.log('newName is: ' + newName);
                scope.name = newName;
            }
        },
        template: '<input ng-model="updatedName" placeholder="new name value"> <button ng-click="updateName(updatedName)">Update</button>'
    }
})

Please check out the fiddle

4

3 回答 3

52

Although @user1737909 already referenced the SO question to read (What are the nuances of scope prototypal / prototypical inheritance in AngularJS?, which will explain the problem and recommended various ways to fix it), we normally try to give the answer on SO.

So, the reason your fiddle doesn't work is because when a primitive type (i.e., a string, number, or boolean type) is written to -- e.g., scope.name = newName -- the "write" always goes to the local scope/object. In other words, the child scope gets its own name property that shadows the parent property of the same name. The fix is to use an object, rather than a primitive type, in the parent scope. The child scope will then get a reference to that object. Any writes to the object properties (whether from the parent or the child) will go to that one object. (The child scope does not get its own object.)

$scope.obj = {name: 'Dave'};

Then in your directive:

scope.obj.name = newName;

and HTML:

Hello, {{obj.name}}!

fiddle

于 2013-05-30T22:15:09.087 回答
15

Scope inheritance is not meaning setting the value of a child is setting the value of its parent.

Instead of doing scope.name = newName on the child scope, add a method to the parent scope, which will do the same job but on the parent scope, and call it from the child scope since the child inherits this method.

于 2013-05-30T21:20:21.153 回答
6

Within your link function you would write to the parent scope(the global "$scope" scope) like so: scope.$parent.name = newName;

于 2014-07-26T01:47:31.967 回答