为什么我的 JQuery 自定义数据验证在提交时没有执行?
Why my JQuery custom data validation don't get executed on submit?
我想弄清楚为什么当我按下下面的 "submit"(即分享)按钮时我的自定义验证(即 IsEmailValid
方法)没有被执行。 Required
执行得很好,但我的自定义验证属性 - IsEmailAttribute
没有被调用。有人可以指点一下吗。
那是我的 index.cshtml 我的表单是通过 Html.RenderPartial
:
呈现的
@using System.Security.Principal
@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.ViewModels.WorkbookViewModel
@section BodyFill
{
<div id="shareFormContainer">
@{ Html.RenderPartial("_ShareView", new WorkbookShareModel());}
</div>
<table class="table">
<tbody>
@foreach (var workbook in Model.Workbooks)
{
<tr class="@trClassName">
<td>@Html.ActionLink(linkText, "Open", "OpenAnalytics", new { id = Model.Id, workbook = workbook.Name })</td>
<td class="last-modified-date" title="Last Modified Date">@workbook.ModifiedDate.ToShortDateString()</td>
<td class="share">
<button title="Share" class="share-button" onclick='showSharingView("@workbook.Name", "@workbook.Id", "@Model.Id")'> </button>
</td>
</tr>
}
</tbody>
</table>
}
@section Scripts
{
<!--Load JQuery 'unobtrusive' validation -->
@await Html.PartialAsync("_ValidationScriptsPartial")
<script type="text/javascript">
function showSharingView(title, workbookId, id) {
var isEmailAdapterName = 'isEmail';
$('#shareFormModal').modal("show");
// client-side email validation
$.validator.addMethod(isEmailAdapterName, IsEmailValid);
// register the 'isEmail' attribute with the 'unobtrusive' validation
$.validator.unobtrusive.adapters.add(isEmailAdapterName,
[],
function(options) {
// add a 'isEmail' rule to the options so that JQuery can find it when it's checking the rules collection
options.rules.isEmail = {};
// add a message for the 'isEmail' rule ('message' will have the 'ShareModel' attribute 'ErrorMessage' value)
options.messages[isEmailAdapterName] = options.message;
});
}
function hideDialog() {
var form = $("#partialform");
// only hide the dialog if the form is valid
if (form.valid()) {
$('#shareFormModal').modal("hide");
}
}
// Helper method that validates list of emails
function IsEmailValid(emailList, element, parameters) {
// EMAIL VALIDATION LOGIC HERE
}
</script>
}
那是我的模特:
public class WorkbookShareModel
{
[HiddenInput]
public string Id { get; set; }
[HiddenInput]
public string WorkbookId { get; set; }
[HiddenInput]
public string Title { get; set; }
[Required(ErrorMessageResourceType = typeof(Resources.BaseLanguage), ErrorMessageResourceName = "Email_Requirement_Warning")]
[IsEmailAttribute(ErrorMessageResourceType = typeof(Resources.BaseLanguage), ErrorMessageResourceName = "Email_Invalid_Message")]
public IList<string> Emails { get; set; }
}
public class IsEmailAttribute : ValidationAttribute, IClientModelValidator
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var share = (WorkbookShareModel)validationContext.ObjectInstance;
foreach (var email in share.Emails)
{
var convertedEmail = email.Trim().ToLower();
var match = Regex.Match(convertedEmail, Constants.EmailPattern);
// if one of the emails does not match the pattern, break out of the look and return the error message
if (!match.Success)
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes, "data-val-isEmail", errorMessage);
}
private void MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
return;
attributes.Add(key, value);
}
}
}
这是我的表格:
@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.Models.WorkbookShareModel
<!-- Modal -->
<div onclick="activateShareButtons()" class="modal fade" id="shareFormModal" role="dialog">
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 id="dialogDisplayTitle" class="modal-title">THIS VALUE IS SET VIA JAVASCRIPT</h4>
</div>
@using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post, new { @id = "partialform" }))
{
<div class="modal-body">
<label>@BaseLanguage.Share_workbook_Instruction_text</label>
<div class="form-group">
<textarea class="form-control" asp-for="Emails" rows="4" cols="50" placeholder="@BaseLanguage.ShareDialogPlaceholder"></textarea>
<span asp-validation-for="Emails" class="text-danger"></span>
</div>
<input asp-for="Title" />
<input asp-for="Id" />
<input asp-for="WorkbookId"/>
</div>
<div class="modal-footer">
<button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
<button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
}
</div>
</div>
</div>
我设法通过将 $.validator.addMethod
和 $.validator.unobtrusive.adapters.add
方法调用移到 showSharingView
方法之外解决了我的问题。那行得通并且我的自定义错误显示正确。但是,我不确定为什么:
<script type="text/javascript">
var isEmailAdapterName = 'isEmail';
// client-side email validation
$.validator.addMethod(isEmailAdapterName, IsEmailValid);
// register the 'isEmail' attribute with the 'unobtrusive' validation
$.validator.unobtrusive.adapters.add(isEmailAdapterName,
[],
function(options) {
// add a 'isEmail' rule to the options so that JQuery can find it when it's checking the rules collection
options.rules[isEmailAdapterName] = {};
// add a message for the 'isEmail' rule ('message' will have the 'ShareModel' attribute 'ErrorMessage' value)
options.messages[isEmailAdapterName] = options.message;
});
function showSharingView(title, workbookId, id) {
$('.share-button').prop('disabled', true); // Disable all share buttons to avoid opening multiple dialogs
// reset the 'Emails' textarea
$('#Emails').val('');
// set the dialog's control values
$('#Title').val(title);
$('#Id').val(id);
$('#WorkbookId').val(workbookId);
// set the dialog's title
$('#dialogDisplayTitle').html("Share Workbook - " + title);
$('#shareFormModal').modal("show");
}
我想弄清楚为什么当我按下下面的 "submit"(即分享)按钮时我的自定义验证(即 IsEmailValid
方法)没有被执行。 Required
执行得很好,但我的自定义验证属性 - IsEmailAttribute
没有被调用。有人可以指点一下吗。
那是我的 index.cshtml 我的表单是通过 Html.RenderPartial
:
@using System.Security.Principal
@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.ViewModels.WorkbookViewModel
@section BodyFill
{
<div id="shareFormContainer">
@{ Html.RenderPartial("_ShareView", new WorkbookShareModel());}
</div>
<table class="table">
<tbody>
@foreach (var workbook in Model.Workbooks)
{
<tr class="@trClassName">
<td>@Html.ActionLink(linkText, "Open", "OpenAnalytics", new { id = Model.Id, workbook = workbook.Name })</td>
<td class="last-modified-date" title="Last Modified Date">@workbook.ModifiedDate.ToShortDateString()</td>
<td class="share">
<button title="Share" class="share-button" onclick='showSharingView("@workbook.Name", "@workbook.Id", "@Model.Id")'> </button>
</td>
</tr>
}
</tbody>
</table>
}
@section Scripts
{
<!--Load JQuery 'unobtrusive' validation -->
@await Html.PartialAsync("_ValidationScriptsPartial")
<script type="text/javascript">
function showSharingView(title, workbookId, id) {
var isEmailAdapterName = 'isEmail';
$('#shareFormModal').modal("show");
// client-side email validation
$.validator.addMethod(isEmailAdapterName, IsEmailValid);
// register the 'isEmail' attribute with the 'unobtrusive' validation
$.validator.unobtrusive.adapters.add(isEmailAdapterName,
[],
function(options) {
// add a 'isEmail' rule to the options so that JQuery can find it when it's checking the rules collection
options.rules.isEmail = {};
// add a message for the 'isEmail' rule ('message' will have the 'ShareModel' attribute 'ErrorMessage' value)
options.messages[isEmailAdapterName] = options.message;
});
}
function hideDialog() {
var form = $("#partialform");
// only hide the dialog if the form is valid
if (form.valid()) {
$('#shareFormModal').modal("hide");
}
}
// Helper method that validates list of emails
function IsEmailValid(emailList, element, parameters) {
// EMAIL VALIDATION LOGIC HERE
}
</script>
}
那是我的模特:
public class WorkbookShareModel
{
[HiddenInput]
public string Id { get; set; }
[HiddenInput]
public string WorkbookId { get; set; }
[HiddenInput]
public string Title { get; set; }
[Required(ErrorMessageResourceType = typeof(Resources.BaseLanguage), ErrorMessageResourceName = "Email_Requirement_Warning")]
[IsEmailAttribute(ErrorMessageResourceType = typeof(Resources.BaseLanguage), ErrorMessageResourceName = "Email_Invalid_Message")]
public IList<string> Emails { get; set; }
}
public class IsEmailAttribute : ValidationAttribute, IClientModelValidator
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var share = (WorkbookShareModel)validationContext.ObjectInstance;
foreach (var email in share.Emails)
{
var convertedEmail = email.Trim().ToLower();
var match = Regex.Match(convertedEmail, Constants.EmailPattern);
// if one of the emails does not match the pattern, break out of the look and return the error message
if (!match.Success)
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes, "data-val-isEmail", errorMessage);
}
private void MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
return;
attributes.Add(key, value);
}
}
}
这是我的表格:
@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.Models.WorkbookShareModel
<!-- Modal -->
<div onclick="activateShareButtons()" class="modal fade" id="shareFormModal" role="dialog">
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 id="dialogDisplayTitle" class="modal-title">THIS VALUE IS SET VIA JAVASCRIPT</h4>
</div>
@using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post, new { @id = "partialform" }))
{
<div class="modal-body">
<label>@BaseLanguage.Share_workbook_Instruction_text</label>
<div class="form-group">
<textarea class="form-control" asp-for="Emails" rows="4" cols="50" placeholder="@BaseLanguage.ShareDialogPlaceholder"></textarea>
<span asp-validation-for="Emails" class="text-danger"></span>
</div>
<input asp-for="Title" />
<input asp-for="Id" />
<input asp-for="WorkbookId"/>
</div>
<div class="modal-footer">
<button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
<button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
}
</div>
</div>
</div>
我设法通过将 $.validator.addMethod
和 $.validator.unobtrusive.adapters.add
方法调用移到 showSharingView
方法之外解决了我的问题。那行得通并且我的自定义错误显示正确。但是,我不确定为什么:
<script type="text/javascript">
var isEmailAdapterName = 'isEmail';
// client-side email validation
$.validator.addMethod(isEmailAdapterName, IsEmailValid);
// register the 'isEmail' attribute with the 'unobtrusive' validation
$.validator.unobtrusive.adapters.add(isEmailAdapterName,
[],
function(options) {
// add a 'isEmail' rule to the options so that JQuery can find it when it's checking the rules collection
options.rules[isEmailAdapterName] = {};
// add a message for the 'isEmail' rule ('message' will have the 'ShareModel' attribute 'ErrorMessage' value)
options.messages[isEmailAdapterName] = options.message;
});
function showSharingView(title, workbookId, id) {
$('.share-button').prop('disabled', true); // Disable all share buttons to avoid opening multiple dialogs
// reset the 'Emails' textarea
$('#Emails').val('');
// set the dialog's control values
$('#Title').val(title);
$('#Id').val(id);
$('#WorkbookId').val(workbookId);
// set the dialog's title
$('#dialogDisplayTitle').html("Share Workbook - " + title);
$('#shareFormModal').modal("show");
}