asp.net mvc 3 - MVC 3 field mandatory if another field is filled -
i have simple question.
i have example 2 fileds mapped on model ex: textbox_1 , textbox_2.
i whant ask if exist way (ex mandatory decorator) imposes textbox_2 mandatory if fill textbox_1. if not fill textbox_1 textbox 2 optional.
is there elegant way ?
there no out of box solution in asp.net mvc this. here attribute created solve it. there 3 available usages attribute:
- pass
nulltargetvalueconstructor: required when dependent field null. - pass value
tagetvalue: required when dependent field equals passed in value. - pass
"*"tagetvalue: required when dependent field populated.
in case need pass "*" targetvalue constructor, meaning dependent property can non null value.
note: contains both, server , client side (+ unobtrusive) validation.
server side attribute class:
public class requiredifattribute : validationattribute, iclientvalidatable { protected requiredattribute _innerattribute; public string dependentproperty { get; set; } public object targetvalue { get; set; } public bool allowemptystrings { { return _innerattribute.allowemptystrings; } set { _innerattribute.allowemptystrings = value; } } public requiredifattribute(string dependentproperty, object targetvalue) { _innerattribute = new requiredattribute(); dependentproperty = dependentproperty; targetvalue = targetvalue; } protected override validationresult isvalid(object value, validationcontext validationcontext) { // reference property validation depends upon var containertype = validationcontext.objectinstance.gettype(); var field = containertype.getproperty(dependentproperty); if (field != null) { // value of dependent property var dependentvalue = field.getvalue(validationcontext.objectinstance, null); // trim spaces of dependent value if (dependentvalue != null && dependentvalue string) { dependentvalue = (dependentvalue string).trim(); if (!allowemptystrings && (dependentvalue string).length == 0) { dependentvalue = null; } } // compare value against target value if ((dependentvalue == null && targetvalue == null) || (dependentvalue != null && (targetvalue == "*" || dependentvalue.equals(targetvalue)))) { // match => means should try validating field if (!_innerattribute.isvalid(value)) // validation failed - return error return new validationresult(formaterrormessage(validationcontext.displayname), new[] { validationcontext.membername }); } } return validationresult.success; } public virtual ienumerable<modelclientvalidationrule> getclientvalidationrules(modelmetadata metadata, controllercontext context) { var rule = new modelclientvalidationrule { errormessage = formaterrormessage(metadata.getdisplayname()), validationtype = "requiredif", }; string depprop = builddependentpropertyid(metadata, context viewcontext); // find value on control depend on; // if it's bool, format javascript style // (the default true or false!) string targetvalue = (targetvalue ?? "").tostring(); if (targetvalue bool) targetvalue = targetvalue.tolower(); rule.validationparameters.add("dependentproperty", depprop); rule.validationparameters.add("targetvalue", targetvalue); yield return rule; } private string builddependentpropertyid(modelmetadata metadata, viewcontext viewcontext) { // build id of property string depprop = viewcontext.viewdata.templateinfo.getfullhtmlfieldid(dependentproperty); // unfortunately have name of current field appended beginning, // because templateinfo's context has had fieldname appended it. instead, // want context though 1 level higher (i.e. outside current property, // containing object, , hence same level dependent property. var thisfield = metadata.propertyname + "_"; if (depprop.startswith(thisfield)) // strip off again depprop = depprop.substring(thisfield.length); return depprop; } } client side (including unobtrusive validation):
$.validator.addmethod('requiredif', function (value, element, parameters) { var id = '#' + parameters['dependentproperty']; // target value (as string, // that's actual value be) var targetvalue = parameters['targetvalue']; targetvalue = (targetvalue == null ? '' : targetvalue).tostring(); // actual value of target control // note - needs cater more // control types, e.g. radios var control = $(id); var controltype = control.attr('type'); var actualvalue = controltype === 'checkbox' ? control.attr('checked').tostring() : control.val(); // if condition true, reuse existing // required field validator functionality if ($.trim(targetvalue) === $.trim(actualvalue) || ($.trim(targetvalue) === '*' && $.trim(actualvalue) !== '')) return $.validator.methods.required.call( this, value, element, parameters); return true; }); $.validator.unobtrusive.adapters.add( 'requiredif', ['dependentproperty', 'targetvalue'], function (options) { options.rules['requiredif'] = { dependentproperty: options.params['dependentproperty'], targetvalue: options.params['targetvalue'] }; options.messages['requiredif'] = options.message; });
Comments
Post a Comment