Reputation: 8834
I'm making a custom auto-complete directive that uses an <input>
within itself, but I'm having a bit trouble figuring out how to pass the 'required' attribute down, other attributes that have values I can see but 'required' appears to be blank whether it is set or not. The first part of my return statement below:
return {
restrict: 'E',
template: tpl,
replace: true,
scope: {
suggestionsPath: '=autoComplete',
method: '@method',
term: '@term',
required: '@required',
ngModel: "="
}...
thanks!
Upvotes: 5
Views: 3914
Reputation: 143
I know this is an old question, but for others who come looking (which is how I ended up here):
you can pass the required tag to the directive to be read as a boolean, and then use that value in ng-required.
return {
restrict: 'E',
template: tpl,
replace: true,
scope {
required:'@'
}
Then in your directive template you would use it as
<input type="text" ng-required="required" />
Either the attribute 'required' is found and is then set to true in the directive, or the attribute is not found which will be interpreted by ng-required as a false value
Upvotes: 2
Reputation: 14574
I've built a few extensions to inputs and the best (arguably) only way to extend existing ngModel bindings is using the ngModelController in your directive. You can require another directive's controller by using the "require" property. The documentation for ngModelController is here
This will allow you to get/set the model values as well as extend or replace the validation behavior as needed. Because you are now probably extending in combination AngularJS input directives you will also probably want to look at the input directives inside AngularJS for examples of how this work. They also can work in tangent with the ngFormController as a parent for the whole form. This took me a while to grasp so be patient but it is by far the best way to do this.
I would avoid isolate scopes here, they can be tricky, don't always play well with other directives (so typically only use it on new elements or things where only one directive will exists on it's own). I would design something like this:
return {
restrict: 'E',
template: tpl,
replace: true,
require: 'ngModel',
link: function(scope, element, attrs, ngModelController) {
// Use attrs to access values for attributes you have set on the lement
// Use ngModelController to access the model value and add validation, parsing and formatting
// If you have an attribute that takes an expression you can use the attrs value along with $scope.$watch to check for changes and evaluate it or the $parse service if you just want to evaluate it.
}
I recommend getting as familiar as you can with directive design as custom inputs can get pretty tricky depending on what they do (we have built custom inputs that add +/- buttons as well as ones that format numbers as percentages, currencies or just numbers with commas while you type into them). Aside from the ngModelController docs these are useful to review:
Upvotes: 4
Reputation: 6746
Required is a bit of a funny attribute by itself (see here Setting an attribute named "required" and any value, with JQuery, doesn't work). You will likely have a lot of trouble passing any sort of value through on this as its effect is determined by whether it is present, not by its value. Different browsers will treat it differently and may rewrite the value.
You will also have trouble because both required
and ngModel
are directives that will be compiled on your element if they are provided. required
will talk to ngModel
and you will need to implement ngModel
properly if you want things to work.
A simpler option is to rename required
and ngModel
to other names. e.g. myRequired
and myNgModel
. You can then bind ng-model
directly to scope.myNgModel
and bind an ng-required
to myRequired
.
Upvotes: 2