jquery-validation-unobtrusive icon indicating copy to clipboard operation
jquery-validation-unobtrusive copied to clipboard

Unable to override errorPlacement function using $.validator.setDefaults()

Open MikeAlhayek opened this issue 6 years ago • 16 comments

I am trying to change the error placement to fit css-bootstrap3

I added the following code before I included jquery.validate.unobtrusive v3.2.9

But my errorPlacement function never gets called. also adding errorClass: "help-block" does not override the jquery.validate.unobtrusive default class-name.

$(function () {
        $.validator.setDefaults({
            errorElement: "span",
            errorClass: "help-block",
            highlight: function (element, errorClass, validClass) {
            	console.log('Also, the param errorClass returns input-validation-error instead of help-block', errorClass, validClass, element);
                var elm = $(element);
                var group = elm.closest('.form-group');
                
                if(group.length == 0) {
                    group = elm.closest('.form-group-custom');
                }

                if(group.length) {
                    group.addClass('has-error');
                }
            },
            unhighlight: function (element, errorClass, validClass) {
                console.log('Also, the param errorClass returns input-validation-error instead of help-block', errorClass, validClass, element);

                var elm = $(element);
                var group = elm.closest('.form-group');
                
                if(group.length == 0) {
                    group = elm.closest('.form-group-custom');
                }

                if(group.length) {
                    group.removeClass('has-error');
                }
            },
            errorPlacement: function (error, element) {

            	console.log('errorPlacement... this never gets called :(', error, element);
                var elm = $(element);

                if (elm.parent('.input-group').length || elm.parent('.input-group-custom').length) {
                    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);
                }
            },
            submitHandler: function (form) {
                showLoading();
                form.submit();
            }
        });
    });

MikeAlhayek avatar Apr 20 '18 17:04 MikeAlhayek

Thanks for contacting us, @CrestApps. @SteveSandersonMS , any suggestions? Thanks!

mkArtakMSFT avatar Apr 24 '18 17:04 mkArtakMSFT

@CrestApps Are you able to share a repro sample?

jbagga avatar May 01 '18 22:05 jbagga

@CrestApps Please let us know if https://stackoverflow.com/questions/5487139/how-can-i-customize-the-unobtrusive-validation-in-asp-net-mvc-3-to-match-my-styl is not helpful. Or provide a working repro sample and I can investigate further. Thanks!

jbagga avatar May 04 '18 17:05 jbagga

@jbagga that does not work. In fact, that's the order I have my scripts included. I will try to create a repo to share when time permits.

MikeAlhayek avatar May 04 '18 21:05 MikeAlhayek

Hi @CrestApps. Can you please share a repro project with us to help with investigation?

mkArtakMSFT avatar May 08 '18 20:05 mkArtakMSFT

@mkArtakMSFT @jbagga I created a repo to demonstrate the problem https://github.com/CrestApps/MvcWithUnobtrusive

The project is an Asp.Net MVC 5, I used VS 2013 to create it.

The current order in which my scripts are included are as follow

  1. /Scripts/jquery-1.10.2.js
  2. /Scripts/bootstrap.js
  3. /Scripts/jquery.validate.js
  4. /Scripts/jquery.validate.setup.js
  5. /Scripts/jquery.validate.unobtrusive.js

If you wish to include /Scripts/jquery.validate.setup.js before /Scripts/jquery.validate.unobtrusive.js, simply rename /Scripts/jquery.validate.setup.js to /Scripts/jquery.validate.unobtrusive.setup.js then re-run the app.

As you can see when you run the project, the validation never calls errorPlacement function,

screenshot_10

I hope this helps

MikeAlhayek avatar May 09 '18 00:05 MikeAlhayek

@CrestApps Thank you for the project. I am able to see this repro.

I have a work around for now and tagging @kichalla to look at it and see if the product code needs to change.

I split the jquery.validate.setup.js file into two: one that overrides highlight and unhighlight functions from jquery.validate.js (same as yours without errorPlacement function) and another that overrides the errorPlacement function in jquery.validate.unobstrusive.js

To override errorPlacement I created jquery.validate.unobtrusive.setup.js:

var settings = {
    errorElement: "span",
    errorClass: "help-block",
    errorPlacement: function (error, element) {
        console.log('errorPlacement function was called');
        console.log('errorPlacement... this never gets called :(', error, element);
        var elm = $(element);

        if (elm.parent('.input-group').length || elm.parent('.input-group-custom').length) {
            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);
        }
    },
    submitHandler: function (form) {
        showLoading();
        form.submit();
    }
}
$.validator.unobtrusive.options = settings;

The (relevant) order in the _Layout file is:

    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/jqueryval/setup")

    @Scripts.Render("~/bundles/jqueryval/unobtrusive")
    @Scripts.Render("~/bundles/jqueryval/unobtrusive/setup")

Where "~/bundles/jqueryval/setup" is the jquery.validate.setup.js script and "~/bundles/jqueryval/unobtrusive/setup" is the jquery.validate.unobtrusive.setup.js script.

Output: image

PR with the changes I described (so it's easier to compare) https://github.com/CrestApps/MvcWithUnobtrusive/pull/1

jbagga avatar May 09 '18 18:05 jbagga

@CrestApps Is your issue solved with the above suggestion?

jbagga avatar May 11 '18 20:05 jbagga

@jbagga yes. I hope there is a fix coming up for this in a future releases as what you provided is a workaround.

Thank you

MikeAlhayek avatar May 11 '18 21:05 MikeAlhayek

Thanks @jbagga for looking into this. @javiercn, can you please continue this investigation as @jbagga will be out from the next week? Thanks!

mkArtakMSFT avatar May 11 '18 22:05 mkArtakMSFT

Looking for a solution as well. This would make integration of existing themes much easier!

li0nsar3c00l avatar Jun 01 '18 19:06 li0nsar3c00l

Any reason why $.validator.defaults doesn't get passed on to $.validator.unobtrusive.options by default? That would surely simplify things a bit…

Nettsentrisk avatar Aug 16 '18 07:08 Nettsentrisk

Agreed with @Nettsentrisk. I've been using ASP.NET Core with jQuery Unobtrusive Validation for about a year now, and trying to modify the default validation behavior has always been a nightmare since we have no control over when $.validate() is called and $.validator.setDefaults() seems to only work sporadically. There at least needs to be some official info on the Model Validation topic about how to change the jQuery Validate settings correctly within ASP.NET Core.

Rabadash8820 avatar Aug 25 '18 21:08 Rabadash8820

@li0nsar3c00l @Nettsentrisk @Rabadash8820 Check out the link in this issue for an excellent workaround.

lonix1 avatar Oct 14 '18 13:10 lonix1

I'm having the same problem. @danroth27 any idea when this is going to be fixed?

ferronsw avatar Jan 22 '19 11:01 ferronsw

I fall into the same issue, any update?

ahedreville avatar Aug 02 '19 10:08 ahedreville

Closing in favor of https://github.com/dotnet/aspnetcore/issues/8573

javiercn avatar Oct 19 '22 10:10 javiercn