[英]Custom validation not firing client-side
我正在編寫一個自定義屬性,以便在另一個屬性具有指定值時要求viewmodel中的屬性。
我使用這篇文章作為參考: RequiredIf Conditional Validation Attribute
但是一直遇到IClientModelValidator的.NET Core修訂版的問題。 具體來說,服務器端驗證按預期工作,ModelState.IsValid返回false,ModelState錯誤包含我的自定義錯誤代碼。 在不同版本的驗證器之間進行翻譯時,我覺得我遺漏了一些東西。
舊(工作)解決方案具有以下內容:
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata,
ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessageString,
ValidationType = "requiredif",
};
rule.ValidationParameters["dependentproperty"] =
(context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(PropertyName);
rule.ValidationParameters["desiredvalue"] = DesiredValue is bool
? DesiredValue.ToString().ToLower()
: DesiredValue;
yield return rule;
}
基於此處概述的IClientModelValidator的更改: https : //github.com/aspnet/Announcements/issues/179我編寫了以下方法:
public void AddValidation(ClientModelValidationContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes, "data-val-requiredif", errorMessage);
MergeAttribute(context.Attributes, "data-val-requiredif-dependentproperty", PropertyName);
var desiredValue = DesiredValue.ToString().ToLower();
MergeAttribute(context.Attributes, "data-val-requiredif-desiredvalue", desiredValue);
}
private bool MergeAttribute(
IDictionary<string, string> attributes,
string key,
string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
這些是按預期調用的,並且值已正確填充,但忽略了以下JS。 讓我懷疑我錯過了兩者之間的某些東西。
$.validator.addMethod("requiredif", function (value, element, parameters) {
var desiredvalue = parameters.desiredvalue;
desiredvalue = (desiredvalue == null ? "" : desiredvalue).toString();
var controlType = $("input[id$='" + parameters.dependentproperty + "']").attr("type");
var actualvalue = {}
if (controlType === "checkbox" || controlType === "radio") {
var control = $("input[id$='" + parameters.dependentproperty + "']:checked");
actualvalue = control.val();
} else {
actualvalue = $("#" + parameters.dependentproperty).val();
}
if ($.trim(desiredvalue).toLowerCase() === $.trim(actualvalue).toLocaleLowerCase()) {
var isValid = $.validator.methods.required.call(this, value, element, parameters);
return isValid;
}
return true;
});
$.validator.unobtrusive.adapters.add("requiredif", ["dependentproperty", "desiredvalue"], function (options) {
options.rules["requiredif"] = options.params;
options.messages["requiredif"] = options.message;
});
有任何想法嗎?
編輯:只是為了消除服務器端正常工作的疑問,問題幾乎肯定在客戶端,這里是一個裝飾字段生成的HTML片段:
<input class="form-control" type="text" data-val="true" data-val-requiredif="Profession Other Specification is Required" data-val-requiredif-dependentproperty="ProfessionTypeId" data-val-requiredif-desiredvalue="10" id="ProfessionOther" name="ProfessionOther" value="" placeholder="Please Specify Other">
所以我有與原始提問者相同的設置和相同的結果。 通過逐步調試自定義驗證器的項目以及它們不被觸發的位置,我能夠確定在最初加載頁面時,jquery.validate.js將驗證器對象附加到表單。 工作項目的驗證器包含我創建的自定義驗證器的密鑰。 沒有工作的驗證器缺少該密鑰(后來在我發布表單時添加並可用)。
不幸的是,由於驗證器對象已經創建並附加到沒有我的自定義驗證器的表單,它從未到達該函數。 解決這一問題的關鍵是要動我的兩個JS功能jQuery的准備功能外 ,盡量靠近我的主要腳本的頂部越好(就在我把我的jQuery的驗證器的默認值)。 我希望這有助於其他人!
我的項目是用TypeScript編寫的,所以我的結構有點不同,但實際添加驗證器的JavaScript保持不變。
這是我的“SometimesRequired”驗證器Typescript類的代碼:
export class RequiredSometimesValidator {
constructor() {
// validator code starts here
$.validator.addMethod("requiredsometimes", function (value, element, params) {
var $prop = $("#" + params);
// $prop not found; search for a control whose Id ends with "_params" (child view)
if ($prop.length === 0)
$prop = $("[id$='_" + params + "']");
if ($prop.length > 0) {
var ctrlState = $prop.val();
if (ctrlState === "EditableRequired" && (value === "" || value === "Undefined"))
return false;
}
return true;
});
$.validator.unobtrusive.adapters.add("requiredsometimes", ["controlstate"], function (options) {
options.rules["requiredsometimes"] = options.params["controlstate"];
options.messages["requiredsometimes"] = options.message;
});
// validator code stops here
}
}
然后在我的boot-client.ts文件(為我的應用程序的JavaScript提供動力的主文件)中,我在文檔之外實例化上面的驗證器的新副本(因此調用構造函數,該構造函數將自定義驗證器添加到內存中的驗證器對象) 。准備好了
export class Blueprint implements IBlueprint {
constructor() {
// this occurs prior to document.ready
this.initCustomValidation();
$(() => {
// document ready stuff here
});
}
private initCustomValidation = (): void => {
// structure allows for load of additional client-side validators
new RequiredSometimesValidator();
}
}
作為一個不使用TypeScript的簡單示例,您應該能夠這樣做:
<script>
$.validator.addMethod("requiredsometimes", function (value, element, params) {
var $prop = $("#" + params);
// $prop not found; search for a control whose Id ends with "_params" (child view)
if ($prop.length === 0)
$prop = $("[id$='_" + params + "']");
if ($prop.length > 0) {
var ctrlState = $prop.val();
if (ctrlState === "EditableRequired" && (value === "" || value === "Undefined"))
return false;
}
return true;
});
$.validator.unobtrusive.adapters.add("requiredsometimes", ["controlstate"], function (options) {
options.rules["requiredsometimes"] = options.params["controlstate"];
options.messages["requiredsometimes"] = options.message;
});
$(function() {
// document ready stuff
});
</script>
解決這個問題的關鍵是將我的兩個JS函數移到jQuery ready函數之外,盡可能靠近我的主腳本頂部(就在我設置jQuery驗證器默認值之后)。 我希望這有助於其他人!
歸功於@ Loni2Shoes
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.