Incorrect jQuery validation ignores the cancel class on the submit button if used on an Ajax form

I am trying to do additional client-side validation using

  • ASP.NET MVC 4,
  • unobtrusive jQuery validation,
  • unobtrusive ajax

That works great

The following figures show what I mean with additional client-side validation: It is assumed that only one field in my form will contain email, so an email validator will be attached to it.

enter image description here

Now we click on save. Since our text "name @doamin" is not a valid email address, a summary of the verification results is displayed. Along with the check summary, we don’t open the Save Anyway button.

enter image description here

This second button is a regular submit button that has class="cancel" . This instructs the jQuery.validate.js script to skip validation when jQuery.validate.js with this button.

Here is a snippet of view code:

 @using (Html.BeginForm()) { <div> <input data-val="true" data-val-email="Uups!" name="emailfield" /> <span class="field-validation-valid" data-valmsg-for="emailfield" data-valmsg-replace="false">*</span> </div> <input type="submit" value="Save" /> @Html.ValidationSummary(false, "Still errors:") <div class="validation-summary-valid" data-valmsg-summary="true"> <input type="submit" value="Save anyway" class="cancel" /> </div> } 

All of this works great.

Problem

The second submit button, “Save Anyway,” stops working as expected if I go to the Ajax form. It just behaves like normal and prevents sending until validation completes successfully.

Here is the "ajaxified" code snippet:

 @using (Ajax.BeginForm("Edit", new { id = "0" }, new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "ajaxSection", })) { <div> <input data-val="true" data-val-email="Uups!" name="emailfield" /> <span class="field-validation-valid" data-valmsg-for="emailfield" data-valmsg-replace="false">*</span> </div> <input type="submit" value="Save" /> @Html.ValidationSummary(false, "Still errors:") <div class="validation-summary-valid" data-valmsg-summary="true"> <input type="submit" value="Save anyway" class="cancel" name="saveAnyway" /> </div> } 

I debugged jQuery.validation.js to find out what the difference is, but failed.

Qustion

Any ideas on how to fix or work around the problem and let the ajax form behave as intended, welcome.


Adding

To confirm customer-side validation is an absolute must. Server side validation is not an option. In addition to higher traffic (this example is a simplification - the real form contains much more fields) and latency, there is one thing whose server-side verification will not be performed: client-side validators highlight erroneous fields when the focus is lost. This means that you have feedback as soon as you move on to the next field.

+6
source share
3 answers

This is a well-known limitation of Microsoft unobtrusive ajax script. You can change it to fix the error. Therefore, inside the jquery.unobtrusive-ajax.js script, replace the following line 144:

 $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []); 

from:

 $(form).data(data_click, name ? [{ name: name, value: evt.target.value, className: evt.target.className }] : []); 

In addition, we pass the class name to the handler so that it can decide whether it should trigger a client-side check or not. Currently, it always invokes a check no matter which button was pressed. And now on line 154 we change the following test:

 if (!validate(this)) { 

from:

 if (clickInfo[0].className != 'cancel' && !validate(this)) { 

so that the client-side check no longer works if the submit button was used to submit the form with the class name canceled. Another possibility is to clear the jquery.unobtrusive-ajax.js script and replace your Ajax.BeginForm with the standard Html.BeginForm , which you could unobtrusively use AJAXify to use plain old jQuery.

+11
source

FINALLY I figured out a solution that is unobtrusive in itself

  // restore behavior of .cancel from jquery validate to allow submit button // to automatically bypass all jquery validation $(document).on('click', 'input[type=image].cancel,input[type=submit].cancel', function (evt) { // find parent form, cancel validation and submit it // cancelSubmit just prevents jQuery validation from kicking in $(this).closest('form').validate().cancelSubmit = true; $(this).closest('form').submit(); return false; }); 

Note. If at the first attempt it seems that this does not work, make sure that you are not accessing the server and not refreshing the error page. You will have to bypass server-side validation in other ways - it just allows you to submit the form without having to add .ignore attributes to everything in your form.

(you may need to add button to the selector if you use buttons)

+6
source

if an unobtrusive check is not required, disable it and perform all your server-side checks.

You can check the value of the "Submit" button on the server side and continue based on this:

add name attribute for both send inputs:

 <input type="submit" value="Save" name="btnSubmit" /> <input type="submit" value="Save anyway" class="cancel" name="btnSubmit" /> 

Update the action to accept string btnSubmit . You can simply put it in your model if you have one.

 [HttpPost] public ActionResult Edit(string emailfield, string btnSubmit) { switch (btnSubmit) { case "Save": if(ModelState.IsValid) { // Save email } break; case "Save anyway": // Save email return RedirectToAction("Success"); break; } // ModelState is not valid // whatever logic to re display the view return View(model); } 

UPDATE

I understand that checking the client simplifies the work, but if you cannot understand what is wrong with Ajax (I am not familiar with this behavior when class = "cancel" is applied to the input), you can write a script that will check the input for sloppy side on server side:

 $('input[type=text]').blur(function(){ $.ajax({ url: '/ControllerName/ValidateInput', data: { inputName: $(this).val() }, success: function(data) { //if there is a validation error, display it }, error: function(){ alert('Error'); } }); }); 

Now you need to create an action that will perform input validation:

 public ActionResult ValidateInput(string inputName) { bool isValid = true; string errorMessage = ""; switch (inputName) { case "password" // do password validation if(!inputIsValid) { isValid = false; errorMessage = "password is invalid"; } break; case "email" // do email validation if(!inputIsValid) { isValid = false; errorMessage = "email is invalid"; } break; } return Json(new { inputIsValid = isValid, message = errorMessage }); } 

This is a bit of a hassle, but, as I said, it can work if you do not figure out a client check.


UPDATE

I don’t know why I didn’t think about it at first ... instead of relying on class="cancel" , you could do something like this:

Give your "anyway" submit input Id:

 <input type="submit" value="Save anyway" class="cancel" name="btnSubmit" id="submitAyway" /> 

Then enter the script as follows:

 $('#submitAyway').click(function(evt) { evt.preventDefault(); $('form').submit(); }); 

I have not tested this, but theoretically this should send the form without checking it. You probably still need server side validation, as I showed in my first example.

-1
source

Source: https://habr.com/ru/post/920890/


All Articles