如何在使用 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 对象。请参阅 了解正确用法。
其次,min
和max
属性仅用于HTML-5验证,与jQuery验证无关。事实上,它们甚至不会工作,因为 jquery.validate.js
将 novalidate="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; }
我有 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 对象。请参阅
其次,min
和max
属性仅用于HTML-5验证,与jQuery验证无关。事实上,它们甚至不会工作,因为 jquery.validate.js
将 novalidate="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; }