简体   繁体   中英

AngularJS directive controller's scope accessible from outside directive, why?

Came across something interesting while experimenting. For some reason I am able to access the scope of a controller specified inside a directive declaration from outside the directive.

Here is the sample code:

myApp.directive('lockToggle', function () {
    return {
        restrict: 'A',
        link: function (scope, elem) {
            elem.bind('click', function (e) {
                scope.locked = !scope.locked;
                scope.$apply();
            });
        },
        controller: function ($scope) {
            $scope.locked = false;
            $scope.hello = function () {
                alert('hello');
            };
        }
    };
});

and here is my markup:

<button lock-toggle>
  Toggle Lock
</button>
<button ng-disabled="locked" ng-click="hello()">
  Click Me!
</button>

When I click on the button Toggle Lock , the Click Me! button disables and enables correctly. And, when I click the Click Me! button, the method hello() on the controllers scope is called.

My question is why? Shouldn't the scope of the controller declared in the directive be isolated to the directives scope in the html? I would expect it to behave in the same way as other controllers, eg:

<!--Can't access the scope of MyController-->

<div ng-controller="MyController">
  .    
  .
  <!--CAN access the scope of MyController-->
  .
  .
</div>

<!--Can't access the scope of MyController-->

But for some reason, this doesn't seem to apply to my earlier example above. Why is this?

You can decide how your directive scope should behave and if it shall inherit from the parent scope:

myApp.directive('lockToggle', function () {
return {
    restrict: 'A',
    scope: {}, // Will create an isolated scope
    link: function (scope, elem) {
        elem.bind('click', function (e) {
            scope.locked = !scope.locked;
            scope.$apply();
        });
    },
    controller: function ($scope) {
        $scope.locked = false;
        $scope.hello = function () {
            alert('hello');
        };
    }
  };
});

Currently, you do not specify a scope attribute, which is equal to scope:false . Therefore, the directive does not create a scope.

Further information

The reason it is accessible is that you are adding it to same scope shared by your parent controller:

controller: function ($scope) {
    $scope.locked = false;
    $scope.hello = function () {
        alert('hello');
    };
}

Here $scope is of your parent controller and since in JavaScript object is by reference so you adding it to your parent controller.

If you want to initialize variable only for directive scope then use scope:

scope:{
  //properties
}

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