jQuery 不显眼的验证来验证表单的一部分

发布于 2024-12-09 08:50:18 字数 1703 浏览 1 评论 0原文

我们有一个 ASP.NET MVC 3 应用程序,它使用不显眼的 jQuery 验证。该页面允许在同一时间内将子对象添加到模型中。

包含子项网格,以及一些用于添加新子项的输入字段。

以问题为模型、子任务为子任务的简化示例:

Issue.cshtml ->定义表单并包括问题及其子任务的字段。

@model Issue
@using (Html.BeginForm("Create", "Issues", FormMethod.Post, new { id = "mainForm" })
{
    @Html.TextBoxFor(model => model.Summary)
    @Html.Partial("SubtaskFields", new Subtask())
    @Html.Partial("SubtasksGrid", model.Subtasks)
}

SubtaskFields.cshtml:

@model Subtask

@Html.TextBoxFor(model => model.Summary)

<button id="add">Add</button>

SubtasksGrid.cshtml:

@model IEnumerable<Subtask>

<table>
    @foreach (var subtask in Model)
    {
        <tr>
            <td>
                @subtask.Name
                <input type="hidden" name="Subtasks[@subtask.Index].Name" value="@subtask.Name"/>
            </td>
        </tr>
    }
</table>

要点是,提交表单时,仅应验证并提交问题的属性(Issue.Name,例如)以及子项的隐藏字段(Subtask.Name,例如) 。

我们有一些 javascript 代码挂钩“添加”按钮,并根据 SubtaskFields.cshtml 部分视图中的值添加新的子任务。该脚本首先验证输入字段。为了实现这一点,我们还为 SubtaskFields.cshtml 使用 TextBoxFor 等 html 帮助器,渲染一个虚拟/默认子任务对象(new Subtask ())。我们的 javascript 在添加新子任务之前使用 $("#mainForm").validate().element(...) 来验证 SubtaskFields。

这种方法的一个大问题是,jQuery 不显眼的验证框架会自动挂钩提交按钮,并在提交表单之前验证表单中的所有字段。即,甚至子任务字段也经过验证。这没有任何意义。假设子任务名称是必填的(这意味着用户只有填写了子任务名称才能单击“添加”)。但是,如果用户没有单击“添加”,则子任务字段中的值没有任何意义,尤其可以留空。在这种情况下,在我们当前的设置中,jQuery 验证失败,因为必填字段留空。

如何解决这个问题?

We have a ASP.NET MVC 3 application that uses unobtrusive jQuery validation. The page allows to add children objects to the model in the same go. The <form> contains a grid for the children, and some input fields for adding new children.

Simplified example with Issue as the Model and Subtasks as the children:

Issue.cshtml -> Defines the form and includes fields for the issue as well as its subtasks.

@model Issue
@using (Html.BeginForm("Create", "Issues", FormMethod.Post, new { id = "mainForm" })
{
    @Html.TextBoxFor(model => model.Summary)
    @Html.Partial("SubtaskFields", new Subtask())
    @Html.Partial("SubtasksGrid", model.Subtasks)
}

SubtaskFields.cshtml:

@model Subtask

@Html.TextBoxFor(model => model.Summary)

<button id="add">Add</button>

SubtasksGrid.cshtml:

@model IEnumerable<Subtask>

<table>
    @foreach (var subtask in Model)
    {
        <tr>
            <td>
                @subtask.Name
                <input type="hidden" name="Subtasks[@subtask.Index].Name" value="@subtask.Name"/>
            </td>
        </tr>
    }
</table>

The point is, when submitting the form, only the properties of the issue (Issue.Name, e.g.), plus the hidden fields for the children (Subtask.Name, e.g.) should be validated and submitted.

We have some javascript code that hooks on the "add" button, and adds a new subtask based on the values in the SubtaskFields.cshtml partial view. That script validates the input fields first. In order for this to work, we use the TextBoxFor etc. html helpers for the SubtaskFields.cshtml, too, rendering a dummy/default Subtask object (new Subtask()). Our javascript the uses $("#mainForm").validate().element(...) to validate the SubtaskFields before adding a new subtask.

The big problem with this approach is that the jQuery unobtrusive validation framework automatically hooks on the submit button and validates all fields within the form before submitting the form. I.e., even the subtask fields are validated. This does not make any sense. Say that the subtask name is mandatory (which means the user can only click on "add" if he has filled in a subtask name). But if the user does not click on "add", the values in the Subtask Fields don't have any meaning and can in particular be left blank. In this case, in our current setting, jQuery validation fails because a mandatory field was left blank.

How can this be solved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

烟燃烟灭 2024-12-16 08:50:18

这就是我们的想法:

  1. 向所有子任务字段添加一个属性(提交表单时不应验证该属性),例如“data-val-ignore”。
  2. 对于添加按钮,将表单验证器上的 ignore 设置为 "[data-val-ignore]"
  3. 以便验证子任务字段(通常会被忽略) ,迭代它们,对于每个字段,删除属性,重新解析以生成规则,执行验证,添加属性,再解析一次。

广告 2:

$(document).ready(function () {
    $.data($('form')[0], 'validator').settings.ignore = "[data-val-ignore]";
});

广告 3:

$(allSubtaskFields).each(function() {
    $(this).removeAttr("data-val-ignore");
    $.validator.unobtrusive.parseElement(this, false);
    if (!$("mainForm").validate().element($(this))) { result = false; }
    $(this).attr("data-val-ignore", "true");
    $.validator.unobtrusive.parseElement(this, false);
});

This is what we've come up with:

  1. Add an attribute to all subtask fields (which should not be validated when submitting the form), e.g. "data-val-ignore".
  2. Set the ignore setting on the form's validator to "[data-val-ignore]"
  3. For the add button, in order to validate the subtask fields (which are normally ignored), iterate over them, and for each field, remove the attribute, re-parse to genereate the rules, execute validation, add the attribute, parse one more time.

Ad 2:

$(document).ready(function () {
    $.data($('form')[0], 'validator').settings.ignore = "[data-val-ignore]";
});

Ad 3:

$(allSubtaskFields).each(function() {
    $(this).removeAttr("data-val-ignore");
    $.validator.unobtrusive.parseElement(this, false);
    if (!$("mainForm").validate().element($(this))) { result = false; }
    $(this).attr("data-val-ignore", "true");
    $.validator.unobtrusive.parseElement(this, false);
});
栀子花开つ 2024-12-16 08:50:18

我建议将 @Html.Partial("SubtasksGrid", model.Subtasks) 移到表单之外,并将其放在一个单独的表单中,或者让部分为每个网格行生成一个表单。

这将解决主表单的验证问题,并且还应该允许您简化 SubTasksGrid 中每一行的验证。

I would suggest moving @Html.Partial("SubtasksGrid", model.Subtasks) outside of your form, and either having it in a single separate form, or have the partial generate a form for each grid row.

This will address your validation problems with your main form, and should also permit you to simplify validation of each row in SubTasksGrid.

遗忘曾经 2024-12-16 08:50:18

要验证表单的一部分,请将要验证的部分或控件包装到带有 #id.class 的 div 中,然后执行以下操作:

var validator = $("#myForm").validate();
var isValid = true;
$("myDivToBeValidated").find("*[data-val]").each(function (indx, elem) {
if (!validator.element(elem)) {
    isValid = false;
}
});

//this part of form is valid however there might be some other invalid parts 
if (isValid) 
   //do your action, like go to next step in a wizard or any other action
   goToNextStep();

我希望它是清楚了,如果不清楚请留言。有关 jQuery 验证插件element() 函数的更多信息,检查此

To validate part of the form, wrap the section or the controls you want to validate into a div with an #id or .class and do the following:

var validator = $("#myForm").validate();
var isValid = true;
$("myDivToBeValidated").find("*[data-val]").each(function (indx, elem) {
if (!validator.element(elem)) {
    isValid = false;
}
});

//this part of form is valid however there might be some other invalid parts 
if (isValid) 
   //do your action, like go to next step in a wizard or any other action
   goToNextStep();

I hope it is clear, if not please leave a comment. For more info about jQuery validation plugin and element() function, check this

风吹雨成花 2024-12-16 08:50:18

看起来您正在与 MVC 引擎对抗。
我将使用编辑器模板和显示模板,为您想要验证和发布的内容使用 EditorFor 模板,为您不想发布和验证的内容使用显示模板。如果显示模板中有 TextBoxFor,请确保其绑定属性没有必需的属性,如果它是值类型,则使其可为空。

Looks like you are working against the MVC egine here.
I would use Editor templates and Display templates, EditorFor template for the stuff you wanna validate and post, and Display template for the stuff you dont wanna post and validate.. If you have a TextBoxFor in the display template make sure its binding property has no Required attribute, and if its a value type make it nullable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文