I might be thinking about this completely backwards, but I'm trying to make three nested directives, lets call them: screen, component and widget. I want widget to be able to trigger some behavior in component, which in turn triggers some behavior in screen. So:
.directive('screen', function() { return { scope: true, controller: function() { this.doSomethingScreeny = function() { alert("screeny!"); } } } }) .directive('component', function() { return { scope: true, controller: function() { this.componentFunction = function() { WHAT.doSomethingScreeny(); } } } }) .directive('widget', function() { return { scope: true, require: "^component", link: function(scope, element, attrs, componentCtrl) { scope.widgetIt = function() { componentCtrl.componentFunction(); }; } } }) <div screen> <div component> <div widget> <button ng-click="widgetIt()">Woo Hoo</button> </div> </div> </div>
I can require parent components in a widget's link fn using require: "^component"
, but how do I further give components controller access to its containing screen?
What I need is the WHAT in component so when you click the widget's button it alerts "screeny!".
Thanks.
AngularJS ng-controller Directive The ng-controller directive adds a controller to your application. In the controller you can write code, and make functions and variables, which will be parts of an object, available inside the current HTML element. In AngularJS this object is called a scope.
A controller is usually used to contain and maintain the logic for your view, which gets bound to your view via $scope. A directive is something that you might use repeatedly and is called in your view directly through the directive name which you can pass in as an attribute.
... is quite illustrative as AngularJS doesn't allow multiple directives (on the same DOM level) to create their own isolate scopes. According to the documentation, this restriction is imposed in order to prevent collision or unsupported configuration of the $scope objects.
Angular scopes include a variable called $parent (i.e. $scope. $parent ) that refer to the parent scope of a controller. If a controller is at the root of the application, the parent would be the root scope ( $rootScope ). Child controllers can therefore modify the parent scope since they access to it.
Here are two ways you could solve your problem:
scope: true
, all scopes prototypically inherit. So if you define your methods on $scope
instead of on this
in the screen
controller, then both component
and widget
will have access to function doSomethingScreeny
. component
and require: '^screen'
. In the link function, save the screenCtrl to a scope property, then you can access it in the directive's controller (inject $scope
). Most of this stuffs fails when you want to directly access properties or methods from the parent controller on controller creation. I found another solution by using dependency injection and using the $controller
service.
.directive('screen', function ($controller) { return { require: '^parent', scope: {}, link: function (scope, element, attr, controller) { $controller('MyCtrl', { $scope: scope, $element: element, $attr, attr, controller: controller }); } } }) .controller('MyCtrl, function ($scope, $element, $attr, controller) {});
This method is better testable and does not pollute your scope with unwanted controllers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With