Reputation: 39250
I would like to validate email and phone based on the following:
If both email and phone are empty or the value containing them are not valid then both are invalid with message "Please provide either a valid email or phone number."
If the email address is invalid then it's invalid with possibly the above message plus "This is not a valid email address.", same for the phone.
Here is what I got so far:
The template/html:
<input type="email" name="email" class="form-control"
id="useredit:email"
data-ng-model="userInfo.email"
data-user-validate='email'
>
<span class="glyphicon form-control-feedback"
data-ng-class="setValidGlyph(userEdit.email,'mail');"
data-ng-show='!userEdit.email.$pristine'
data-tooltip-html-unsafe=
"{{getValidateMessage(userEdit.email,'email');}}"
data-tooltip-trigger='click'
data-tooltip-placement='bottom'
data-tooltip-append-to-body='true'
></span>
setValidGlyph comes from appSettings and figures out what glyph to show:
setValidGlyph:function(input,fieldName){
return {
'glyphicon-info-sign':input.$error[fieldName] && !input.$pristine
,'glyphicon-ok': !input.$error[fieldName] && !input.$pristine
};
}
getValidateMessage comes from appRules and will show message(s) depending on on what the validator function has set true (see code later).
data-tooltip is ui bootstrap tooltip.
The directive:
angular.module('app').directive('userValidate'
, ['appSettings', 'appRules', function(appSettings,appRules) {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
var fn=appRules.user.validate(attrs.userValidate);
ctrl.$parsers.unshift(
function(viewValue){
fn(viewValue,ctrl);
}
);
ctrl.$error.messages=
appRules.user.validateMessages[attrs.userValidate];
}
};
}]);
the apprules:
angular.module('app').factory('appRules'
, ['appSettings',function(appSettings){
var appRules = {
user:{
validate:function(name){
return appRules.user.validateFunctions[name];
},
validateFunctions: {
email:function(viewValue,ctrl){
// mail indicates if this box is valid or not used for css
ctrl.$setValidity('mail'
, appRules.general.isEmail(viewValue));
//specific to see if email is valid
//removed isEmail to make code shorter
ctrl.$setValidity('invalidEmail'
, appRules.general.isEmail(viewValue));
}
},
getValidateMessage:function(ctrl,name){
var ret = [],i=-1,len=ctrl.$error.messages.length;
while(++i<len){
if(ctrl.$error[ctrl.$error.messages[i]]){
ret.push('<p>');
ret.push(appSettings
.userFailMessages[ctrl.$error.messages[i]]);
ret.push('</p>');
}
}
return ret.join('');
},
validateMessages: {
name:['emptyName'],
email:['invalidEmail','phoneOrEmail']
}
}
};
return appRules;
}]
);
appSettings.userFailMessages is in appSettings and looks like this:
appSettings.userFailMessages.invalidEmail="Please provide a valid email.";
In appRules.validateFunctions.email I would like to access phone.$pristine and phone.$error but arguments passed are only the current input control and that has no access to the form it's on.
How could I access this? Maybe somewhere in the template I can set the form with:
{{setForm(userEdit);}}
Where userEdit is the name of the form and setForm is a method of appRules but it seems kind of sloppy.
Reason for validation and messages to be in rules and settings is because I am uncomfortable having domain rules and error messages in my template.
Upvotes: 2
Views: 661
Reputation: 108471
If you need access to the form in your directive, you need to require it:
require: ['^form', 'ngModel'],
link: function($scope, elem, attrs, ctrls) {
var form = ctrls[0];
var ngModel = ctrls[1];
if(form) {
// use form to get whatever it is you care about.
var whatever = form[otherProperty].$error.something;
}
}
So given the above, you should be able to pass the form controller into your custom validation methods as a third argument, and handle whatever you need.
I hope this helps.
Upvotes: 4