What's going on here?
Here are my directives:
// template <input ng-model="theModel" />
app.directive('bseInput', function () {
return {
templateUrl: "/Scripts/bse/bse-inputs.html",
scope:
{
theModel: '=',
},
compile: function compile(tElement, tAttrs, transclude) {
// do stuff
}
};
});
app.directive('submitRequired', function (objSvc) {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
// do something
}
};
});
Here is an example of the directive in use:
<input bse-input submit-required="true" the-model="someModel"></input>
Here is the actual error text:
Error: [$compile:ctreq] Controller 'ngModel', required by directive 'submitRequired', can't be found! http://errors.angularjs.org/1.2.2/$compile/ctreq?p0=ngModel&p1=submitRequired at http://www.domain.ca/Scripts/angular/angular.js:78:12 at getControllers (http://www.domain.ca/Scripts/angular/angular.js:5972:19) at nodeLinkFn (http://www.domain.ca/Scripts/angular/angular.js:6139:35) at compositeLinkFn (http://www.domain.ca/Scripts/angular/angular.js:5550:15) at nodeLinkFn (http://www.domain.ca/Scripts/angular/angular.js:6132:24) at compositeLinkFn (http://www.domain.ca/Scripts/angular/angular.js:5550:15) at publicLinkFn (http://www.domain.ca/Scripts/angular/angular.js:5458:30) at http://www.domain.ca/Scripts/angular/angular.js:1299:27 at Scope.$get.Scope.$eval (http://www.domain.ca/Scripts/angular/angular.js:11634:28) at Scope.$get.Scope.$apply (http://www.domain.ca/Scripts/angular/angular.js:11734:23) angular.js:9159 (anonymous function) angular.js:9159 $get angular.js:6751 nodeLinkFn angular.js:6141 compositeLinkFn angular.js:5550 nodeLinkFn angular.js:6132 compositeLinkFn angular.js:5550 publicLinkFn angular.js:5458 (anonymous function) angular.js:1299 $get.Scope.$eval angular.js:11634 $get.Scope.$apply angular.js:11734 (anonymous function) angular.js:1297 invoke angular.js:3633 doBootstrap angular.js:1295 bootstrap angular.js:1309 angularInit angular.js:1258 (anonymous function) angular.js:20210 trigger angular.js:2315 (anonymous function) angular.js:2579 forEach angular.js:300 eventHandler angular.js:2578ar.js:7874
Just in case, that the above <input>
snippet does not contain a typo, this is the issue:
the-model
we need ng-model
<input bse-input submit-required="true" ng-model="someModel.Property"></input>
angular is using normalized/denormalized naming conventions, which at the end means: ng-model
is the html way how to express the ngModel
. HTML is case insensitive... and this solves this issue
Suggestion. If we are working with multiple directives applied to one element:
We should let both of them to work with a standard INPUT settings. So, both should could require ng-model, as a way how to access the model passed to input.
if the-model should be representing different setting, which is absolutely ok, we just do not have to skip passing the ng-model as well
About require
:
When you have nested directives that need to communicate with each other, the way to do this is through a controller.
Other directives can have this controller passed to them with the require property syntax. The full form of require looks like:
require: '^?directiveName'
Explanations of the require string:
directiveName
: This camel-cased name specifies which directive the controller should come from. So if our
directive needs to find a controller on its parent , we’d write it as myMenu.^
By default, Angular gets the controller from the named directive on the same element. Adding this optional
^ symbol says to also walk up the DOM tree to find the directive. For the example, we’d need
to add this symbol; the final string would be \^myMenu.?
If the required controller is not found, Angular will throw an exception to tell you about the problem. Adding
a ? symbol to the string says that this controller is optional and that an exception shouldn’t be thrown if not
found. Though it sounds unlikely, if we wanted to let s be used without a
container, we could add this for a final require string of ?\^myMenu.