jquery validate default setting ignore ":hidden", after version 1.9.0. http://bassistance.de/2011/10/07/release-validation-plugin-1-9-0/
在 asp.net mvc使用 [attribute]驗證輸入資料的時候,有個 radio button一直沒有觸發驗證…卡了半天,把頁面其他欄位拿掉還是不動,一怒之下把 html, javascript複製到 jsbin居然就能跑?
想不到什麼好方法,一項一項比對差異,本機 jquery.validate是 1.10,jsbin上拿別人的範例來改是載入 cdn的 1.8,嗯……體力耗盡,改日再戰 Orz
登登登,一日過去。
$("form").validate().element("#my_column") // 用這個方法試我的欄位到底有沒有驗證,得到 js執行錯誤,好的開始!
// 發現它會去呼叫內部的 check()
// check()會呼叫 validationTargetFor()
validationTargetFor: function(element) {
// if radio/checkbox, validate first element in group instead
if (this.checkable(element)) {
element = this.findByName( element.name ).not(this.settings.ignore)[0];
}
return element;
},
// this.settings.ignore = ":hidden" 很熟悉的 jquery selector
// 回頭看 css,設計為了自訂 radio button style的確有隱藏 radio & checkbox
確定原因,解法就單純了:
// http://stackoverflow.com/a/8565769/4963421
$.validator.setDefaults({
ignore: []
});
// or
$(function () {
$('#myform').validate({ // 好像因為 unobtrusive的關係,原本的預設值有被另外複製一份,所以這樣改不會生效
ignore: [],
// any other options and/or rules
});
$("form").data("validator").settings.ignore = [];// 要這樣硬來
})
終於動了 Q_Q
順便記錄 MVC自訂驗證邏輯步驟:
// checkbox = true檢查 elemNames、checkbox = false檢查 falseCheckElemNames
public class CheckBoxConditionRequiredAttribute : ValidationAttribute, IClientValidatable
{
private const string _defaultErrorMessage = "The Value field is required.";
private string[] _elemNames;
private string[] _falseCheckElemNames;
public CheckBoxConditionRequiredAttribute(string[] elemNames, string[] falseCheckElemNames = null)
{
_elemNames = elemNames;
_falseCheckElemNames = falseCheckElemNames;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null)
{// checkbox 沒值不檢查
return null;
}
bool result = true, chkValue = false;
bool.TryParse(value.ToString(), out chkValue);
if (chkValue)
{
foreach (var item in _elemNames)
{
var itemValue = Convert.ToString(validationContext.ObjectType.GetProperty(item).GetValue(validationContext.ObjectInstance, null));
if (string.IsNullOrEmpty(itemValue))
{
result = false;
break;
}
}
}
else
{// false時要填的欄位
if (_falseCheckElemNames != null)
{
foreach (var item in _falseCheckElemNames)
{
var itemValue = Convert.ToString(validationContext.ObjectType.GetProperty(item).GetValue(validationContext.ObjectInstance, null));
if (string.IsNullOrEmpty(itemValue))
{
result = false;
break;
}
}
}
}
if (!result)
{
string errorMsg = this.ErrorMessageString;
if (string.IsNullOrEmpty(this.ErrorMessage))
{
if (this.ErrorMessageResourceType != null && !string.IsNullOrEmpty(this.ErrorMessageResourceName))
{
errorMsg = ErrorMessageResourceType.GetProperty(ErrorMessageResourceName).GetValue(ErrorMessageResourceType) as string;
}
else
{
errorMsg = _defaultErrorMessage;
}
}
return new ValidationResult(errorMsg);
}
return null;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
string errorMsg = this.ErrorMessageString;
if ((this.ErrorMessageResourceType == null || string.IsNullOrEmpty(this.ErrorMessageResourceName)) && string.IsNullOrEmpty(this.ErrorMessage))
{
errorMsg = _defaultErrorMessage;
}
ModelClientValidationRule rule = new ModelClientValidationRule
{
ErrorMessage = string.Format(errorMsg),
ValidationType = "checkboxconditionrequired"
};
// 此參數一定要是小寫!
rule.ValidationParameters.Add("obj", metadata.PropertyName);
rule.ValidationParameters.Add("domelemnames", string.Join(",", _elemNames));
rule.ValidationParameters.Add("falsecheckelem", string.Join(",", _falseCheckElemNames));
yield return rule;
}
}
[CheckBoxConditionRequired(new string[] { "input_while_true" }, falseCheckElemNames: new string[] { "input_while_false" }
, ErrorMessageResourceType = typeof(resourceType)
, ErrorMessageResourceName = "resourceProperty"
)]
public bool flag { get; set; }
public string input_while_true { get; set; }
public string input_while_false { get; set; }
<script src="/Scripts/jquery.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
<script>
$.validator.addMethod("checkboxconditionrequired", function (value, element, params) {
var obj = $('#' + params['obj']),
domelemNames = params['domelemnames'].split(","),
falsecheckelem = (params["falsecheckelem"] || "").split(","),
isChecked = obj[0].checked,
result = true;
if (isChecked) {
$.each(domelemNames, function (index, value) {
if ($("#" + value).val() == "") {
result = false;
return false;
}
});
}
else {
if (falsecheckelem.length > 0) {
$.each(falsecheckelem, function (index, value) {
if ($("#" + value).val() == "") {
result = false;
return false;
}
});
}
}
return result;
});
$.validator.unobtrusive.adapters.add(
'checkboxconditionrequired', ['obj', 'domelemnames', 'falsecheckelem'],
function (options) {
options.rules['checkboxconditionrequired'] = {
obj: options.params['obj'],
domelemnames: options.params['domelemnames'],
falsecheckelem: options.params['falsecheckelem']
};
if (options.message != null) {
$.validator.messages.checkboxconditionrequired = options.message;
}
}
);
</script>