I have this directive which can be required or not. It can be used in two ways (as far as I know)
<my-foo required></my-foo>
or
<my-foo ng-required="data.value > 10"></my-foo>
So, because require
and ngRequire
are basically the same thing you would think that the directive could do this
HTML:
<my-foo ng-require="data.isRequired"></my-foo>
JS:
...
.directive('myFoo', function () {
return {
restrict: 'E',
scope: {
required: '='
}
...
Well, nope, this doesn't work, scope.require
is undefined
. You actually have to change the scope definition to
scope: {
required: '=ngRequired'
}
So the question is what is the preferred way to handle both situation such that the value gets stored in scope.required
? Should I defined both or use attrs from the link function ?
There are basically 2 approaches you can pick:
ng-model
If you peek at the ng-required
directive source code you'll find it only deals with ng-model
controller:
restrict: 'A',
require: '?ngModel',
link: function(scope, elm, attr, ctrl) {
if (!ctrl) return;
attr.required = true; // force truthy in case we are on non input element
ctrl.$validators.required = function(modelValue, viewValue) {
return !attr.required || !ctrl.$isEmpty(viewValue);
};
attr.$observe('required', function() {
ctrl.$validate();
});
}
Thus if you custom directive supports ng-model
you already have support for ng-required
i.e.:
angular.module('test', [])
.directive('myInput', function(){
return {
restrict: 'E',
require: 'ngModel',
scope: true,
template: '<div><button ng-click="changeValue()">Change Value from: {{currentValue}}</button></div>',
link: function (scope, element, attrs, ngModelCtrl) {
ngModelCtrl.$parsers.push(function(val){
if(!val){
return null;
}
return parseFloat(val, 10) * 100;
});
ngModelCtrl.$render = function() {
scope.currentValue = ngModelCtrl.$viewValue || 'No value';
};
scope.changeValue = function read(){
var newValue = Math.random();
if(newValue > 0.5){
ngModelCtrl.$setViewValue(newValue + "");
} else {
ngModelCtrl.$setViewValue(null);
}
ngModelCtrl.$render();
};
}
};
});
ng-required
:angular.module('test', [])
.directive('myFormElement', function() {
return {
restrict: 'E',
scope: {
model: '=',
required: '='
},
template: '<div>Enter number: <input type="number" ng-model="data.number" ng-required="required"></div>'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-init="data={value:'Initial', required: false}">
<form>
Is required: <input type="checkbox" ng-model="data.required">
<my-form-element required="data.required" model="data"></my-form-element>
</form>
</div>