How to clear jquery validate errors
Asked Answered
B

7

16

I'm hijaxing an existing form and POSTing to the server. jQuery validate does most of the validation but if validation fails on the server we return the errors to the client as JSON.

Below is the code that does that:

<script type="text/javascript">

    $(function () {

        $("form").submit(function (e) {
            var $form = $(this);
            var validator = $form.data("validator");

            if (!validator || !$form.valid())
                return;

            e.preventDefault();

            $.ajax({
                url: "@Url.Action("index")",
                type: "POST",
                data: $form.serialize(),
                statusCode: {
                    400: function(xhr, status, err) {                           
                        var errors = $.parseJSON(err);
                        validator.showErrors(errors);
                    }
                },
                success: function() {
                    // clear errors
                    // validator.resetForm();
                    // just reload the page for now
                    location.reload(true);
                }
            });
        });

    });

</script>

The problem is I can't seem to clear the validation errors if the POST is successful. I've tried calling validator.resetForm() but this makes no difference, the error messages added by the showError() call, are still displayed.

Note I'm also using the jQuery.validate.unobtrusive plugin.

Boatswain answered 6/7, 2012 at 10:59 Comment(1)
Just wonder, does this line work for you? validator.showErrors(errors);Alimony
L
36

You posted this a while ago, I don't know if you managed to solve it? I had the same problem with jQuery validate and the jQuery.validate.unobtrusive plugin.

After examining the source code and some debugging, I came to the conclusion that the problem comes from the way the unobtrusive plugin handles error messages. It removes the errorClass that the jQuery.validate plugin sets, and so when the form is reset, jQuery validate cannot find the error labels to remove.

I did not want to modify the code of the plugins, so I was able to overcome this in the following way:

// get the form inside we are working - change selector to your form as needed
var $form = $("form");

// get validator object
var $validator = $form.validate();

// get errors that were created using jQuery.validate.unobtrusive
var $errors = $form.find(".field-validation-error span");

// trick unobtrusive to think the elements were succesfully validated
// this removes the validation messages
$errors.each(function(){ $validator.settings.success($(this)); })

// clear errors from validation
$validator.resetForm();

note: I use the $ prefix for variables to denote variables that contain jQuery objects.

Llano answered 12/2, 2013 at 11:31 Comment(4)
Your requirements were probably slightly different, but I adapted this to simply be $('#someFormId').validate().resetForm();Campobello
@AaronLS. jquery.validade.unobtrusive or not, I had the same problem and your code resolved it. Clean and simple, thanks.Gradual
Great solution. I just added two more lines to remove input-validation-error classes from the input tags. var $inputs = $form.find("input"); $inputs.each(function () { $(this).removeClass("input-validation-error"); });Urinate
Annoying that 5 years down the line almost and we still have to do that! I also noticed that the form has to be visible as well for resetForm() to work. I was flipping to a different tab before resetForm() was called and the form items kept their error message. That said, thank you as this worked once I flipped the tab last.Gillman
R
3

In .NET Core I have the form inside a builtin Bootstrap modal.

For now I'm manually removing the error message spans from their containers, once the modal is starting to show, by using the additional .text-danger class of the error message container like so:

$('#my-form').find('.text-danger').empty();

so that I don't rely on container .field-validation-error that might have been already toggled to .field-validation-valid.

The min.js versions of the libraries jquery.validate and jquery.validate.unobtrusive are loaded via the partial view _ValidateScriptsPartial.cshtml, so I played with them to see what resetForm() / valid() and native html form reset() do.

So in my case $('#my-form').data("validator").resetForm() only resets some validator internals, not the form and it doesn't trigger the onReset() function in the unobtrusive library. The $('#my-form').valid() indeed removes the errors in the modal, but only if the modal is fully shown and valid. The native html form reset() is the only one that triggers both onReset() of unobtrusive library, and then the resetForm() of the validator. So it seems like we need to trigger the native html form document.querySelector('#my-form').reset() to activate the reset functions of both libraries/plugins.

The interesting thing is that the unobtrusive library runs the simple jQuery empty() on the .field-validation-error class (the container of the error span message) only in its onSuccess() function, and not onReset(). This is probably why valid() is able to remove error messages. The unobtrusive onReset() looks like it's responsible only for toggling .field-validation-error class to .field-validation-valid. Hense we are left with a <span id="___-error">The error message</span> inside the container <span class="text-danger field-validation-error">...</span>.

Reprieve answered 13/12, 2020 at 15:8 Comment(0)
H
2
$("#form").find('.field-validation-error span').html('')
Hanoi answered 13/5, 2017 at 11:8 Comment(0)
O
1

May be I am wrong to clear the errors like this:

function clearError(form) {
    $(form + ' .validation-summary-errors').each(function () {
        $(this).html("<ul><li style='display:none'></li></ul>");
    })
    $(form + ' .validation-summary-errors').addClass('validation-summary-valid');
    $(form + ' .validation-summary-errors').removeClass('validation-summary-errors');
    $(form).removeData("validator");
    $(form).removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(form));
};

I tried answer given in the comment by AaronLS but not got the solution so I just do it like this.

Maybe helpful to someone.

Outboard answered 28/2, 2017 at 7:29 Comment(0)
D
1

Here's the code I ended up using to clear/reset all errors. It's possible there's some redundancy in there, but it's working for me.

function removeValidationErrors(frmId) {
    var myform = $('#' + frmId);
    myform.get(0).reset();
    var myValidator = myform.validate();
    $(myform).removeData('validator');
    $(myform).removeData('unobtrusiveValidation');
    $.validator.unobtrusive.parse(myform);
    myValidator.resetForm();
    $('#' + frmId + ' input, select').removeClass('input-validation-error');
}
Diaspora answered 26/12, 2017 at 20:30 Comment(0)
V
0

The reason this is still an issue (even 6 years on) is that jQuery Validation doesn't have an event handler for when your form is valid; only for when it's invalid.

Unobtrusive Validation taps into the Invalid handler to add your errors to your Validation Summary elements. (Specifically, any element with data-valmsg-summary=true.) But because there's no Valid handler, there's no way for Unobtrusive Validation to know when they can be cleared.

However, jQuery Validation does allow you to supply your own showErrors method, which is called after every validation check, whether the result is valid or invalid. Thus, you can write a custom function that will clear those validation summary boxes if your form is valid.

Here's a sample that will apply it globally. (You could apply it to specific instances of your validators by using settings, but since I always want this functionality, I just put it in the defaults object.)

$.validator.defaults.showErrors = function () {
    if (!this.errorList.length) {
        var container = $(this.currentForm).find("[data-valmsg-summary=true]");
        container.find("ul").empty();
        container.addClass("validation-summary-valid").removeClass("validation-summary-errors");
    }

    // Call jQuery Validation's default showErrors method.
    this.defaultShowErrors();
};

This also has the benefit of clearing the validation summary box the moment your form is valid, instead of having to wait for the user to request a form submission.

Vaudevillian answered 31/5, 2018 at 14:15 Comment(0)
C
0

I couldn't find this documented anywhere, but you should be able to reset the form by triggering a specific event, reset.unobtrusiveValidation, to which unobtrusive listens.

Example here:

.validation-summary-valid, .field-validation-valid { display: none; }
.field-validation-error { display: block; color: #dc3545 }
.input-validation-error { border: 1px solid #dc3545 }
.validation-summary-errors { background-color: #dc3545; color: #fff; margin-bottom: .5rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.5/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/4.0.0/jquery.validate.unobtrusive.js"></script>

<form id="testForm">
  <div class="validation-summary-valid" data-valmsg-summary="true">
    Validation Summary:
    <ul><li style="display:none"></li></ul>
  </div>

  <div>
    <label for="first_name">first name:</label>
    <input data-val="true" data-val-required="the 'first name' field is required" name="first_name" id="first_name" />
    <span class="field-validation-valid" data-valmsg-for="first_name" data-valmsg-replace="true"></span>
  </div>

  <div>
    <label for="last_name">last name:</label>
    <input data-val="true" data-val-required="the 'last name' field is required" name="last_name" id="last_name" />
    <span class="field-validation-valid" data-valmsg-for="last_name" data-valmsg-replace="true"></span>
  </div>

  <button type="submit">Submit form (click first)</button>
  <button type="button" onclick="$('#testForm').trigger('reset.unobtrusiveValidation')">Reset form (click second)</button>
</form>
Carcinogen answered 19/9, 2022 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.