How to require a controller in an angularjs directive
I got lucky and answered this in a comment to the question, but I'm posting a full answer for the sake of completeness and so we can mark this question as "Answered".
It depends on what you want to accomplish by sharing a controller; you can either share the same controller (though have different instances), or you can share the same controller instance.
Share a Controller
Two directives can use the same controller by passing the same method to two directives, like so:
app.controller( 'MyCtrl', function ( $scope ) {
// do stuff...
});
app.directive( 'directiveOne', function () {
return {
controller: 'MyCtrl'
};
});
app.directive( 'directiveTwo', function () {
return {
controller: 'MyCtrl'
};
});
Each directive will get its own instance of the controller, but this allows you to share the logic between as many components as you want.
Require a Controller
If you want to share the same instance of a controller, then you use require
.
require
ensures the presence of another directive and then includes its controller as a parameter to the link function. So if you have two directives on one element, your directive can require the presence of the other directive and gain access to its controller methods. A common use case for this is to require ngModel
.
^require
, with the addition of the caret, checks elements above directive in addition to the current element to try to find the other directive. This allows you to create complex components where "sub-components" can communicate with the parent component through its controller to great effect. Examples could include tabs, where each pane can communicate with the overall tabs to handle switching; an accordion set could ensure only one is open at a time; etc.
In either event, you have to use the two directives together for this to work. require
is a way of communicating between components.
Check out the Guide page of directives for more info: http://docs.angularjs.org/guide/directive
Using require in Directive to require a parent Controller
Require is of using other directives controllers in another directive , please refer the below example
var App = angular.module('myApp',[]);
//one directive
App.directive('oneDirective',function(){
return {
restrict: 'E',
controller:function($scope){
$scope.myName= function(){
console.log('myname');
}
}
}
});
//two directive
App.directive('twoDirective',function(){
return {
require:'oneDirective' //one directive used,
link : function(scope,ele,attrs,oneCtrl){
console.log(oneCtrl.myName())
}
}
})
AngularJS directive with require and 2 controllers
You can require
multiple directives. Have it require itself as well as parent
. With this syntax, the last parameter of link
will be an array of the controllers of the given directives.
.directive('test', function () {
return {
restrict: 'A',
require: ['parent', 'test'],
controller: 'TestSomethingController',
link: function (scope, element, attrs, controllers) {
controllers[0].action(); // parent
controllers[1].something(); // self
}
};
});
Here is a forked, working version of your CodePen.
AngularJS directive controllers requiring parent directive controllers?
Here are two ways you could solve your problem:
- Since you are using
scope: true
, all scopes prototypically inherit. So if you define your methods on$scope
instead of onthis
in thescreen
controller, then bothcomponent
andwidget
will have access to functiondoSomethingScreeny
.
Fiddle. - Define a link function on
component
andrequire: '^screen'
. In the link function, save the screenCtrl to a scope property, then you can access it in the directive's controller (inject$scope
).
Fiddle.
Adding a Directive to a Controller using Controller as syntax
Check this fork of your plunk: https://plnkr.co/edit/7iA3JMhuUlvIQN9ORs81?p=preview
.directive('myCustomer', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
controllerAs: 'vm',
controller: ['$scope', function(scope){
console.log(scope.customerInfo);
}],
templateUrl: 'my-customer-iso.html'
};
});
UPD
code should be like so:
(function(angular) {
'use strict';
angular.module('docsIsolateScopeDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' };
$scope.igor = { name: 'Igor', address: '123 Somewhere' };
}])
.directive('myCustomer', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
controllerAs: 'vm',
bindToController: true, //the missing line!!
controller: 'dirCtrl',
templateUrl: 'my-customer-iso.html'
};
})
.controller('dirCtrl', ['$scope', dirCtrl]);
function dirCtrl() {
//var vm = this; //no need in this!
}
})(window.angular);
and
Name: {{vm.customerInfo.name}} Address: {{vm.customerInfo.name}}
in the template
Can I require a controller, in a directive, set with ng-controller?
You can only do:
require: "^ngController"
So, you can't be more specific than that, i.e. you can't ask for "MainCtrl"
or "MyController"
by name, but it will get you the controller instance:
.controller("SomeController", function(){
this.doSomething = function(){
//
};
})
.directive("foo", function(){
return {
require: "?^ngController",
link: function(scope, element, attrs, ctrl){
if (ctrl && ctrl.doSomething){
ctrl.doSomething();
}
}
}
});
<div ng-controller="SomeController">
<foo></foo>
</div>
I don't think, though, that this is a good approach, since it makes the directive very dependent on where it is used. You could follow\ the recommendation in the comments to pass the controller instance directly - it makes it somewhat more explicit:
<div ng-controller="SomeController as ctrl">
<foo ctrl="ctrl"></foo>
</div>
but it still is a too generic of an object and could easily be misused by users of your directive.
Instead, expose a well-defined API (via attributes) and pass references to functions/properties defined in the controller:
<div ng-controller="SomeController as ctrl">
<foo do="ctrl.doSomething()"></foo>
</div>
Angularjs: inject required directive-controller into the controller instead of the link function
Actually there is another way that is less verbose and is used by the angular ngModel itself:
var parentForm = $element.inheritedData('$formController') || ....
Basically they use the fact that the controllers are stored into the data property of the directive dom element.
Still a bit wired, but less verbose and easier to understand.
I don't see a reason why you cannot pass the required controllers into the injection locals for the directive controller.
Related Topics
JavaScript Can't Find Element by Id
Understanding Ajax Cors and Security Considerations
How to Calculate the Latlng of a Point a Certain Distance Away from Another
Why Does Isnan(" ") (String with Spaces) Equal False
Find Out How Long an Ajax Request Took to Complete
Is There Any Difference Between Declared and Defined Variable
JavaScript Use Variable as Object Name
Truncate (Not Round Off) Decimal Numbers in JavaScript
Throwing Strings Instead of Errors
Displaying a Number in Indian Format Using JavaScript
Var Name Produces Strange Result in JavaScript
React.Js: Onchange Event for Contenteditable
Prevent Jquery UI Dialog from Setting Focus to First Textbox
Why Does an Onclick Property Set with Setattribute Fail to Work in Ie
Angular 2: Import External Js File into Component
Extending Built-In Natives in Es6 with Babel
Differencebetween Parseint(String) and Number(String) in JavaScript
How to Use JavaScript or Jquery to Read a Pixel of an Image When User Clicks It