Junior
Junior

Reputation: 11990

How to correctly override "jQuery Unobtrusive Validation" to work for css bootstrap?

I have an ASP.NET MVC 5 base project in which I use css bootstrap for designing my pages.

To work property with css bootstrap. I want to be able to override the default behavior of the errorElement, errorClass, highlight,unhighlight and errorPlacement properties/functions.

This is what I have tried

First, I included the packages in the following order

  1. jQuery (v3.1.1)
  2. jquery.validate.min.js (v1.15.0)
  3. My settings where I override the default behavior (Code below)
  4. jquery.validate.unobtrusive.js (v3.2.3)

This is my first attempt into overriding the package

$.validator.setDefaults({
    errorElement: "span",
    errorClass: "help-block",
    highlight: function (element, errorClass, validClass) {
        $(element).closest('.form-group').addClass('has-error');
    },
    unhighlight: function (element, errorClass, validClass) {
        $(element).closest('.form-group').removeClass('has-error');
    },
    errorPlacement: function (error, element) {

        var elm = $(element);

        console.log('errorPlacement was called');

        if (elm.parent('.input-group').length) {
            console.log('parent');
            console.log(elm.parent());
            error.insertAfter(elm.parent());
        }
        else if (elm.prop('type') === 'checkbox' || elm.prop('type') === 'radio') {
            error.appendTo(elm.closest(':not(input, label, .checkbox, .radio)').first());
        } else {
            error.insertAfter(elm);
        }
    }
});

However, the above code will never call the errorPlacement function, other than that everything else works as expected. But since the errorPlacement method is not being called, the error is being placed in a different place.

Then I changed the above code to this (overriding both jQuery validation and the Unobtrusive)

$.validator.setDefaults({
    errorElement: "span",
    errorClass: "help-block",
    highlight: function (element, errorClass, validClass) {
        console.log('highlight was called');
        $(element).closest('.form-group').addClass('has-error');
    },
    unhighlight: function (element, errorClass, validClass) {
        console.log('highlight was called');
        $(element).closest('.form-group').removeClass('has-error');
    },
    errorPlacement: function (error, element) { }
});

$.validator.unobtrusive.options = {
    errorPlacement: function (error, element) {

        var elm = $(element);
        console.log('errorPlacement was called');

        if (elm.parent('.input-group').length || elm.parent('.input-group-custom').length) {
            console.log('parent');
            console.log(elm.parent());
            error.insertAfter(elm.parent());
        }
        else if (elm.prop('type') === 'checkbox' || elm.prop('type') === 'radio') {
            error.appendTo(elm.closest(':not(input, label, .checkbox, .radio)').first());
        } else {
            error.insertAfter(elm);
        }
    }
};

Now, the function errorPlacement is being called. But, the error is being inserted multiple time. Somehow the code the removes the error message is not being called now.

How can I fix this issue?

Upvotes: 8

Views: 3904

Answers (1)

Jam
Jam

Reputation: 384

This is how I override jQuery Unobtrusive Validation to work with Bootstrap 4.

$.validator.setDefaults({
    errorClass: "",
    validClass: "",
    highlight: function (element, errorClass, validClass) {
        $(element).addClass("is-invalid").removeClass("is-valid");
        $(element.form).find('[data-valmsg-for="' + element.name + '"]').addClass("invalid-feedback");
    },
    unhighlight: function (element, errorClass, validClass) {
        $(element).addClass("is-valid").removeClass("is-invalid");
        $(element.form).find('[data-valmsg-for="' + element.name + '"]').removeClass("invalid-feedback");
    },
});

Copy and paste the code above into a new file. Name it jquery.validate.overrides.js.

Edit BundleConfig.cs. Find the bundle jqueryval. Add path to new file at the end.

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
    "~/Scripts/jquery.validate.js",
    "~/Scripts/jquery.validate.unobtrusive.js",
    "~/Scripts/jquery.validate.overrides.js"
));

To use in a view:

<div class="form-group">
    @Html.LabelFor(m => m.FirstName)
    @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control", placeholder = "First name", type = "text" })
    @Html.ValidationMessageFor(m => m.FirstName)
</div>

Upvotes: 16

Related Questions