What is the meaning of "require: ^"? - javascript

What does the ^ mean under require in this angular directive?
I found this snippet and trying to figure out what it's saying.
.directive('accordionGroupHeading', function() {
return {
restrict: 'EA',
transclude: true,
template: '',
replace: true,
require: '^accordingGroup',
link: function(scope, element, attr, accessibleAccordionGroupCtrl, transclude) {
accessibleAccordionGroupCtrl.setHeading(transclude(scope, function() {}));
}
};
})

The require in this is not about require js it is actually saying that this directive requires a parent of type accordingGroup
take a look at the angular documentation for more info
https://docs.angularjs.org/guide/directive#creating-directives-that-communicate

From https://docs.angularjs.org/guide/directive
The ^^ prefix means that this directive searches for the controller on its parents. (A ^ prefix would make the directive look for the controller on its own element or its parents; without any prefix, the directive would look on its own element only.)
So basically you will have an error if your directive won't find the controller. Using require, you will be able to get access to the controller from the link method of directive.
link: function(scope, element, attrs, controller) {}

Related

Should I avoid adding ngModel as one of the attributes to my angular directive?

To properly work with ngModel I have to use ngModelController, but it provides much more flexibility than I need. Most of the time all I need is to have ngModel as yet another = attribute of the directive. So I often do this:
angular.module('oneClickRegistrationApp')
.directive('myDirective', [function () {
restrict: 'E',
scope: {
ngModel: "=",
},
link: function(scope, element, attrs){
//here I use ngModel as scope.ngModel
}
}]);
I feel that there are some potential downsides to this, but I can't pinpoint them.

Required directive controller is not present on the current DOM element

So I was wondering what actually "required directive controller is not present on the current DOM element" means
here is the link of error:https://docs.angularjs.org/error/$compile/ctreq?p0=ngModel&p1=contenteditable
You are missing the ngModel directive for your custom directive.
Try something like this:
app.directive('contenteditable', function () {
return {
restrict: 'E',
require: 'ngModel',
link: function (scope) {
// do something
}
};
});
and in your HTML file add ng-model
<contenteditable ng-model="name"></contenteditable>
From the angular.js documentation on directives
When a directive uses require, $compile will throw an error unless the specified controller is found. The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix, the directive would look for the controller on just its own element).

AngularJS directive name starts with a number, can't get it to work.

here is my code:
app.directive('3dPlansSlider', function(){
return {
controller: 'projectCtrl',
restrict: 'E',
templateUrl: 'views/3dPlansSlider.html',
link: function(scope, element, attrs){
}
}
});
It is pretty standard in fact, all my directive have exactly this code, but it seems like I'm not able to then import it in my html using the element it created. I'm wondering if there is a way to make it work or it is impossible to get it to work since it starts by a number?
Here is the html:
<3d-plans-slider></3d-plans-slider>
In the page, it doesn't say any errors, it just prints the <3d-plans-slider> (as if it was basic character) but it does not print the closing tag... I'm about to rename it but I figured out there must be a way to make it work.
When you reference your directive, just prepend -data like this:
<data-3d-plans-slider></data-3d-plans-slider>
Keeping your directive defined the same way
app.directive('3dPlansSlider', function(){
return {
controller: 'projectCtrl',
restrict: 'E',
templateUrl: 'views/3dPlansSlider.html',
link: function(scope, element, attrs){
}
}
});

Error 'Multiple Directive Resource Contention' when creating custom directive and using UI-bootstrap

I am trying to create a directive that has as input the rating and which plots stars in the DOM based on this input.
However, when I try the following:
.directive('stars', function (Utils) {
return {
restrict: 'AE', //E = element, A = attribute, C = class, M = comment
transclude: true,
template: "{{starsObj}}",
link: function (scope, element, attrs) {
scope.starsObj = Utils.returnStars(attrs.rating)
}
}
})
where Utils.returnStars(attrs.rating) returns an array (which I would like to use later).
... I get the following error:
Multiple Directive Resource Contention
https://docs.angularjs.org/error/$compile/multidir?p0=rating&p1=%20(module:%20ui.bootstrap.rating)&p2=stars&p3=%20(module:%20noodl.controllers-product)&p4=template&p5=%3Cspan%20ng-mouseleave%3D%22reset()%22%20rating%3D%225%22%3E
Removing ui-bootstrap from my projects resolves the issue, but I do need ui-bootstrap in the end.
What is going on?
You don't need to add 'scope.' prefix to your variables from directive scope, so you should change your template attribute of the directive to this:
return {
restrict: 'AE', //E = element, A = attribute, C = class, M = comment
transclude: true,
template: "{{starsObj}}", //You don't need 'scope.' prefix.
link: function (scope, element, attrs) {
scope.starsObj = Utils.returnStars(attrs.rating)
}
}
Demo on plunker.
UPD: But I see that your error from the console is related to ui-bootstrap. Can you provide code more code, where you use it?
UPD2: The issue here is that ui.bootstrap has his own rating directive. So, to solve this problem you can just rename your rating attribute of stars directive to something else. I updated my plunker.

Requiring a directives controller alongside other required controllers

I have a pair of directives, one lives within the other and requires it using require: '^parentTag'. The two directives also declare their own controllers. Inside of the parent directive I can access its controller as the fourth argument to link: function(scope, el, attrs, ctrl) but in the child this fourth argument is either the required controller or an array of required controllers and the directives controller is no longer accessible.
I've tried to require the controller using the name used in controllerAs 'vm' and also by using the string name for the controller. Neither gets the controller back into that fourth argument.
The controller is accessible from the scope as scope.vm but I'd like to access it via that fourth argument if possible.
This Plunkr shows that the ChildController is not in the fourth argument and only on the scope but the ParentController is accessible as the fourth argument.
http://plnkr.co/edit/2WmB6Bqgc8MEG9JWz4wt
You could require the same directive by its name (never seen anyone actually do it):
function ChildTag() {
return {
restrict: 'AE',
require: ['^parentTag', 'childTag'],
scope: {},
template: '<div class="child-tag">Child</div>',
link: link,
controller: ChildController,
controllerAs: 'vm',
bindToController: true
}
function link(scope, element, attrs, ctrls, transclude) {
// ctrls[1] is ChildController
console.log('Child vm not found in ctrls', ctrls);
console.log('Child vm found on scope', scope.vm);
}
}

Categories

Resources