表單驗證是網頁很常用的功能,通常是submit會觸發驗證流程(會把jQuery.validator.unobtrusive.parse("#form1"); 會把檢核觸發寫在submit button裡)。但今天收到個需求,網頁因為某些因素不想透過submit 表單post資料到後台,想要透過ajax的方式來post資料,但validator又一定需要把要驗證的<input>包在<form>裡面的情況下(如果把<form>拿掉,就不會有驗證效果),要如何觸發表單驗證?
畫面大概上上面長的那樣,照理講應該就是把Barcode<input>跟下面的驗證碼<input>包在同一個<form裡面>,點擊放大鏡<button> submit後,就會post資料到server。但今天收到的需求是不使用submit要透過ajax來做上面的流程,且只有驗證碼欄位需要做表單驗證,測試了一下,終於找出解法。
原本表單部分的cshtml應該如下面:
@using (Html.BeginForm("Index", "Warranty", FormMethod.Post, new { id = "form1" }))
{
<div class="box-body form-row">
<div class="row pccent">
<div class="col-xs-12 form-inline">
@Html.ValidationSummary(true)
@Html.AntiForgeryToken()
<div class="form-group">
<div class="input-group input-group-addon-ddl">
@{
List<SelectListItem> l_ddlType = new List<SelectListItem>();
l_ddlType.Add(new SelectListItem() { Text = Html.Translation("Barcode").ToString(), Value = "Barcode", Selected = true });
}
<div class="input-group-addon">
@Html.DropDownList("SearchType", l_ddlType, new { @class = "form-control", style = "width:auto" })
</div>
@Html.TextBox("barcode", null, new { size = 50, @class = "form-control" })
<div class="input-group-btn">
<button class="btn btn-primary" type="submit" name="fs" id="subbtn"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</div>
</div>
<div class="row pccent form-inline">
<div class="flex-row">
<div class="col-12">
<input name="verifyimage_input" type="text" value="" data-val-required="Please input Verify Code!" data-val="true" class="form-control" placeholder="Verify code" />
</div>
<div class="col-12">
<div class="form-group form-inline">
<div class="input-group-btn">
<div class="input-group">
<img class="pointer tableImg" id="verifyimage" style="border:1px solid #ccc;" src="@Url.Action("JPEG","VerifyImage",new {Area="Common",rdm=eRMA.Common.Utils.GetRandomString(10) })" />
<div onclick="refreshverifyimage();" class="tablebackground"><span class="fas fa-sync-alt tableIcon"></span></div>
</div>
</div>
</div>
</div>
</div>
<div>@Html.ValidationMessage("verifyimage_input")</div>
</div>
</div>
}
不想submit的話,就要把上面的程式稍作修改一下。修改的地方有下面4項:
1.把原本的form改成只包下面驗證碼的部分,這是個沒有submit功能只為了要做JQuery Validation而做的<form>表單。
2.新增加一個hidden <input>,在執行ajax時,把Barcode <input>的值裝進這個hidden <input>的value裡面
3.原本的查詢<button>要用Js加上click事件來執行AJAX
4.觸發驗證方式有兩種:
單一元素驗證可以使用$("input[name=verifyimage_input]").valid()來觸發驗證,
要一次驗證<form>表單裡所有欄位可用$('#{form id}').valid())
這樣就可以達到我們要的有form但又不用submit就可以做表單裡面所有input的驗證了
<div class="box-body form-row">
<div class="row pccent">
<div class="col-xs-12 form-inline">
@Html.ValidationSummary(true)
@Html.AntiForgeryToken()
<div class="form-group">
<div class="input-group input-group-addon-ddl">
@{
List<SelectListItem> l_ddlType = new List<SelectListItem>();
l_ddlType.Add(new SelectListItem() { Text = Html.Translation("Barcode").ToString(), Value = "Barcode", Selected = true });
//l_ddlType.Add(new SelectListItem() { Text = Html.Translation("ProductName").ToString(), Value = "PartNumber" });
}
<div class="input-group-addon">
@Html.DropDownList("SearchType", l_ddlType, new { @class = "form-control", style = "width:auto" })
</div>
@Html.TextBox("barcode", null, new { size = 50, @class = "form-control" })
<div class="input-group-btn">
<button class="btn btn-primary" type="submit" name="fs" id="subbtn"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</div>
</div>
<form id="form1">
<div class="row pccent form-inline">
<div class="flex-row">
<div class="col-12">
<input name="verifyimage_input" type="text" value="" data-val-required="Please input Verify Code!" data-val="true" class="form-control" placeholder="Verify code" />
<input id="hidden_barcode" name="barcode" type="hidden">
</div>
<div class="col-12">
<div class="form-group form-inline">
<div class="input-group-btn">
<div class="input-group">
<img class="pointer tableImg" id="verifyimage" style="border:1px solid #ccc;" src="@Url.Action("JPEG","VerifyImage",new {Area="Common",rdm=eRMA.Common.Utils.GetRandomString(10) })" />
<div onclick="refreshverifyimage();" class="tablebackground"><span class="fas fa-sync-alt tableIcon"></span></div>
</div>
</div>
</div>
</div>
</div>
<div>@Html.ValidationMessage("verifyimage_input")</div>
@*<span data-valmsg-for="verifyimage_input"></span>*@
</div>
</form>
<div id='partial_view'></div>
</div>
補充:
顯示驗證訊息的方式可用:
1.<div>@Html.ValidationMessage("{input element name}")</div≥
=> 可搭配Html.ValidationSummary()做後端驗證,請參考Ref 4.
2.<span data-valmsg-for={input element name}></span>
=> unobtrusive 檢核,請參考Ref 2. & 3.
unobtrusive 前端驗證的觸發前提:
1.必須要在網頁載入時先執行jQuery.validator.unobtrusive.parse("#form1")解析讀取元素的data-val-*標示
2.要被驗證的元素的屬性data-val必須要為true
重設所有欄位回驗證前狀態:
$("#{form_name}")[0].reset(); 可以把所有驗證欄位恢復到網頁剛載入時的狀態
網頁執行中動態設定欄位是否需要驗證:
有些驗證條件是某個條件成立時才需要進行驗證,否則不用驗證,遇到這種情形時,要重新呼叫jQuery.validator.unobtrusive.parse("#{form_name}"),來重新綁定驗證,參考js如下:
$('#{element_id}').attr('data-val', isvalidate);
$('#{element_id}').attr('data-val', isvalidate);
var $form = $('#{form_id}')//表单
//去除表单验证
$form.removeData('validator');
$form.removeData('unobtrusiveValidation');
//重新绑定验证。
$.validator.unobtrusive.parse($form[0]);
Ref:
jQuery Validation Plugin表單驗證使用介紹
使用jQuery.validate.unobtrusive.js-黑暗執行緒
[ASP.NET][MVC] ASP.NET MVC (5) : 資料驗證 (1) Server-side Validation | 小朱® 的技術隨手寫 - 點部落
Validate fields using JQuery validation without any submit? - Stack Overflow
[Asp .Net MVC] MVC Client 端驗證 (Unobtrusive Validate) | Harry's Tech World - 點部落 => 什麼是Unobtrusive可以看這篇