In the project I\'m working on at the moment I currently have three textboxes and I need to validate that at least one of the text boxes has been populated.
I\'ve be
Here is a refactored take on ExpertSystems great post. I didn't need the destroy method so I gutted it.
I also added a grayed out explanation that may help in your code. I use this directive for ALL my required fields. Meaning when I use this directive I no longer use ng-required, or required.
If you want a field required just pass in a unique group name. If you don't want the field required then pass in null, and if you want to have many different groups just pass in a matching group name.
I believe there is a little more refactoring that could be done here. Angularjs states that when using $setValidity, that instead you should use $validators pipeline instead, but I could not get that to work. I am still learning this complex animal. If you have more info, post it!
app.directive('rsPartiallyRequired', function () {
var allinputGroups = {};
return {
restrict: 'A',
require: '?ngModel',
scope: { },
link: function(scope, elem, attrs, ctrl) {
if( !ctrl || !attrs.rsPartiallyRequired ){ return } // no ngModel, or rsPartialRequired is null? then return.
// Initilaize the following on load
ctrl.$formatters.push( validateInputGroup ); // From model to view.
ctrl.$parsers.unshift( validateInputGroup ); // From view to model.
if ( ! allinputGroups.hasOwnProperty( attrs.rsPartiallyRequired )){ // Create key only once and do not overwrite it.
allinputGroups[ attrs.rsPartiallyRequired ] = { isRequired: true } // Set new group name value to { isRequired: true }.
}
scope.inputGroup = allinputGroups[ attrs.rsPartiallyRequired ] // Pass { isRequired: true } to form scope.
function validateInputGroup(value) {
scope.inputGroup[ scope.$id ] = !ctrl.$isEmpty( value ); // Add to inputGroup ex: { isRequired: true, 01E: false }.
scope.inputGroup.isRequired = setRequired( attrs.rsPartiallyRequired ); // Set to true or false.
updateValidity(); // Update all needed inputs based on new user input.
return scope.inputGroup.isRequired ? undefined : value
}
function setRequired(groupName) {
if( ! allinputGroups[ groupName ] ){ return false } // No group name then set required to false.
return Object.keys( allinputGroups[ groupName ] ).every( function( key ) { // Key is 'isRequired' or input identifier.
return ( key === 'isRequired' ) || ! allinputGroups[ groupName ][ key ]
});
}
scope.$watch('scope.inputGroup.isRequired', updateValidity); // Watch changes to inputGroup and update as needed.
function updateValidity() { // Update input state validity when called.
ctrl.$setValidity('required', scope.inputGroup.isRequired ? false : true );
}
}
}
});
// This directive sets input required fields for groups or individual inputs. If an object in the template is given
// to the directive like this:
// Object: { "name": "account_number", "attrs": { "required": { "group": "two" }}}.
// HTML:
// Or anything where the evaluation is a string, for example we could use "groupOne" like this...
// HTML:
// Then this directive will set that group to required, even if it's the only member of group.
// If you don't want the field to be required, simply give the directive a null value, like this...
// HTML:
// However, when you want to use this directive say in an ngRepeat, then just give it a dynamic string for each input
// and link the inputs together by giving the exact matching string to each group that needs at least one field. ex:
//
//
//
//
//
//
//
//
// In the above example, the first and fifth input are not required and can be submitted blank.
// The input with group "two" is the only one in the group, so just that input will be required by itself.
// The 2 inputs with "one" will be grouped together and one or the other will require an input before
// the form is valid. The same will be applied with group "three".
// For this form to be valid, group "two" will be required, and 1 input from group one will be required,
// and 1 input from group three will be required before this form can be valid.