如何在使用 ajax 更新特定字段后触发范围验证

How to fire Range Validation after a particular field is updated using ajax

我有 2 个字段总数量在下拉选择时更新,还有一个字段用于输入应该小于或等于总数量的数量。下拉选择通过 ajax 调用获取数据。我知道 DOM 中动态更新的值需要强制再次解析验证。但它似乎不起作用。所有其他验证在表单中正常工作。 我在 SO 中提到的类似问题 SO1 SO2 尝试过的代码:

   @using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">       
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            @Html.LabelFor(model => model.PurchaseOrderID, "PurchaseOrderID", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.DropDownListFor(u => u.PurchaseOrderID, Model.PurchaseOrders, "--Select--")
                @Html.ValidationMessageFor(model => model.PurchaseOrderID, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.POTotalQuantity, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(model => model.POTotalQuantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })

            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Quantity, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @type = "number", min = "1", max = Model.POTotalQuantity.ToString() } })
                @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.ExpectedDeliveryDate, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-3">
                @Html.EditorFor(model => model.ExpectedDeliveryDate, "{0:dd/mm/yyyy}", new { htmlAttributes = new { @class = "form-control datepicker" } })
                @Html.ValidationMessageFor(model => model.ExpectedDeliveryDate, "", new { @class = "text-danger" })
            </div>
        </div>


        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </div>
    </div>
}

控制器:

 public JsonResult PopulatePODetails(int POID)
    {
        var purchaseOrder = db.PurchaseOrders.Find(POID);

        var poTotalQty = db.PurchaseOrderLineItems.Where(p => p.PurchaseOrderID == purchaseOrder.ID).Sum(q => q.Quantity);

        // Build an anonymous object 
        var data = new
        {
            POTotalQty = poTotalQty

        };
        return Json(data, JsonRequestBehavior.AllowGet);
    }

JS:

 $(document).ready(function () {
//Populating PO quantity on PO selection
    $('#PurchaseOrderID').change(function () {

        if (($(this).val() == "") || ($(this).val() == "0")) {
            //need to clear textbox values
            $('#POTotalQuantity').val('');

        }
        else {
            var poId = $(this).val();

            var url = '@Url.Action("PopulatePODetails", "DeliverySchedules")';
            $.getJSON(url, { POID: poId }, function (response) {
                $('#POTotalQuantity').val(response.POTotalQty);
                $.validator.unobtrusive.parse($(response));
            });
        }
    });


});

型号:

  public class DeliveryScheduleVM
    {
        public int ID { get; set; }
//omitted other properties 
        public IEnumerable<SelectListItem> PurchaseOrders { get; set; }
        [DisplayName("PO Total Qty")]
        public int POTotalQuantity { get; set; }// this is used as the upper limit 
        [Required]
        public int Quantity { get; set; }
    }

首先澄清一下大家的一些误解。

当您重新解析 $.validator 时,您指示 jquery.validate.unobtrusive.js 解析 DOM 并读取表单控件中的 data-val-* 属性(由您的属性验证属性生成) 并将规则添加到 jquery.validate.js。这在第一次加载表单时已经完成,并且只有在您动态添加新的表单控件(例如通过 ajax)时才需要再次这样做,而您没有这样做(您对 Quantity 的控件已经存在)。在任何情况下,您都需要解析 <form> 元素,而不是 json 对象。请参阅 了解正确用法。

其次,minmax属性仅用于HTML-5验证,与jQuery验证无关。事实上,它们甚至不会工作,因为 jquery.validate.jsnovalidate="novalidate" 属性添加到您的 <form> 元素,因为它们不能很好地协同工作。

客户端和服务器端验证都需要的是实现 IClientValidatable 的条件 ValidationAttribute 和相关脚本,以便可以将 Quantity 的值与值进行比较POTotalQuantity。关于编写您自己的条件验证属性的良好指南,我推荐 The Complete Guide To Validation In ASP.NET MVC 3 - Part 2。在您的情况下,您可能会编写一个像

这样使用的属性
[Required]
[Bewteen(1, "POTotalQuantity")]
public int Quantity { get; set; }

如果您不想自己编写,也可以使用 foolproof 插件中的条件验证属性。

下载包(并在您的视图中包含 mvcfoolproof.unobtrusive.js 脚本)并用

装饰您 属性
[Required]
[Range(1, int.MaxValue)] // for minimum value
[LessThanOrEqualTo("POTotalQuantity", ErrorMessage = "The quantity must be less than or equal to the value of POTotalQuantity")]
public int Quantity { get; set; }