All we need is an easy explanation of the problem, so here it is.
I’m trying to create a directive which can be used to reset validation status of multiple input controls in a group, when one of the control’s value is changed. Groups are identified by the attribute of the directive set in HTML.
Ex: – Both of the From Date and To Date inputs resets the validity state when one of the controls input value is changed by the user
This is what I have so far
JS/Angular
angular.module('myModule').directive('groupedInputs', function () {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
element.on('change', function () {
// Resetting own validity
scope.$apply(ctrl.$setValidity('server', true));
// Here I need to set the validity of the controls which
// have the `GroupedInputs` directive with the
// same attribute value
});
}
};
});
HTML
<input name="FromDate" type="date" class="form-control" ng-model="model.FromDate" grouped-inputs="FromToDates">
<input name="ToDate" type="date" class="form-control" ng-model="model.ToDate" grouped-inputs="FromToDates">
It can reset the validity of the own input control, but can not access the other input controls with directive and same attribute value. What is the best possible angular way to access the other controls by querying the inputs with the same attribute?
How to solve :
I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.
Method 1
I would try to approach this problem by implementing helper object to store group elements controllers with methods to add to the group and setValidity of all elements in the group.
Something like this:
angular.module('myModule').directive('groupedInputs', function() {
var groupControls = {
groups: {},
add: function(name, ctrl) {
this.groups[name] = this.groups[name] || [];
this.groups[name].push(ctrl);
},
setValidity: function(name, key, value) {
this.groups[name].forEach(function(ctrl) {
ctrl.$setValidity(key, value);
});
}
};
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, element, attrs, ctrl) {
// Add element controller to the group
groupControls.add(attrs.groupedInputs, ctrl);
element.on('change', function() {
// When needed, set validity of elements in the group
groupControls.setValidity(attrs.groupedInputs, 'server', false);
scope.$apply();
});
}
};
});
Demo: http://plnkr.co/edit/fusaaN6k9J5SZ7iQA97V?p=preview
Method 2
You could store all the controllers having the same group in an array:
angular.module('myModule').directive('groupedInputs', function () {
var controllersPerGroup = {};
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
var groupName = attrs.groupedInputs;
var group = controllersPerGroup[groupName];
if (!group) {
group = [];
controllersPerGroup[groupName] = group;
}
group.push(ctrl);
element.on('change', function () {
// Resetting own validity
scope.$apply(ctrl.$setValidity('server', true));
// all the other controllers of the same group are in the groups array.
});
}
};
});
Don’t forget to take care of removing the controllers once the element is destroyed, by listening to the $destroy
event.
Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0