0

Issue:

Having problems when $.validate() is fired based on forms with inputs having existing values.

I wanted to preface I am new to jQuery's validate and autocomplete plugins, and I may not be understanding some of the options I am utilizing.

My Setup:

I have multiple forms all containing class="update-route" that exists on page load. Each form has multiple inputs with existing values entered that I can display if a user wants to update/edit these existing values. These inputs are <input type='text' name='ABC'> (the input name is arbitrary for this post) where I validate the forms by

$(function() {
    /*
        Function to handle validation for all forms.

    */

    $.validator.setDefaults({
        /*
            Set defaults for error handling messages.

        */

        errorClass: 'is-invalid',
        validClass: 'is-valid',
        highlight: function(element, errorClass, validClass) {
            var form = $(element)
                .closest('form')

            if ($(element)[0].type === 'radio') {
                var inputs = $(element)
                    .closest('.radio-group')
                    .children()
                    .find('input')

                $(inputs)
                    .each(function() {
                        $(this)
                            .removeClass(validClass)
                            .addClass(errorClass)
                    })
            }
            else {
                $(element)
                    .removeClass(validClass)
                    .addClass(errorClass)
            }

        },
        unhighlight: function(element, errorClass, validClass) {
            if ($(element)[0].type === 'radio') {
                var inputs = $(element)
                    .closest('.radio-group')
                    .children()
                    .find('input')

                $(inputs)
                    .each(function() {
                        $(this)
                            .removeClass(errorClass)
                    })
            }
            else {
                $(element)
                    .removeClass(errorClass)
                    .addClass(validClass)
            }

        },
        errorPlacement: function(error, element) {
            $(error)
                .addClass('invalid-feedback')

            if (element[0].type === 'radio') {
                error
                    .insertAfter(element.closest('fieldset'))
            }
            else {
                $(element)
                    .parent()
                    .after(error)
            }
        },
    })

    $.validator.addMethod('autocompleteSelection', function(value, element) {
        /*
            Custom method to verify user chose from ui-autocomplete list.

        */

        return element.classList.contains('autocompleteSelection')
    })

    $("form.update-route")
        .each(function() {
            
            $(this).validate({
                /*
                    onfocusout option is set since Validation plugin evaulates 
                    "lazy" on default when DOM loads.
                */
        
                rules: {
                    RouteID: 'required',
                    ABC: {
                        required: true,
                        autocompleteSelection: true,
                    },
                },
                messages: {
                    RouteID: {
                        required: 'Please enter the Route ID.',
                    },
                    ABC: {
                        required: 'Please choose the Station.',
                        autocompleteSelection: 'Please choose from the list of \
                        stations provided.',
                    },
                },
                onfocusout: function(element) { 
                    $(element).valid(); 
                },
            })
        })
})

To be clear, I made all my inputs have the same name="ABC" so that my $.validate rules can be applied to all of them.

Also utilizing Bootstrap as my CSS and incorporating their server-side validation for CSS styling of the inputs and to display my error messages (meaning I am applying the is-valid and is-invalid classes to inputs using $.validator.setDefaults()) and for error messages I apply the invalid-feedback to the appropriate element.

A little background reference:

I read on stack overflow (here) where I need to modify the jquery.validate.min.js as a work around to validate multiple fields with the same name. Ok I've done that.

I also mentioned I am using jQuery's autocomplete widget. See my code for that below. I wanted to make sure $.validate() can verify the user's input came from the ui-autocomplete list that is provided when a response is made. So I included the options "select" and "change" on $.autocomplete() to add or remove class="autocompleteSelection" respectively - meaning on "select", I add the class and on "change" I remove it. THEN, I add $.validator.addMethod() to return true if the element's classList contains "autocompleteSelection", and I included the method to my "ABC" inputs (as you can see from my code block above).

Also for clarity, because my inputs' value is the human-readable value, but my server needs a immutable value, objectID, I set those values to the input's data attribute.

$(document).on('focus', 'input[name="ABC"]', function(e) {

    var inputs = this

    $(inputs).autocomplete({
        minLength: 3,
        source: function(request, response) {
            $.ajax({
                type: 'GET',
                url: '/ajax/autocomplete',
                dataType: 'json',
                data: {
                    'query': request.term
                },
                success: function(data) {
                    response(
                        jQuery.map(data, function (item) {
                            var site = new Object();
                            site.label = item[0];
                            site.value = item[1];
                            return site
                        })
                    )
                },
            });
        },
        select: function(event, object) {
            event.preventDefault();

            $(this)
                .val(object.item.label)
                .data({
                    'site-object-id': object.item.value
                })

            $(this)
                .addClass('autocompleteSelection')
        },
        focus: function(event, object) {
            event.preventDefault();

            $(this)
                .val(object.item.label)
                .data({
                    'site-object-id': object.item.value
                })
        },
        change: function (event, ui) {
            if(!ui.item){
                $(this).val("")

                $(this)
                    .removeClass('autocompleteSelection')
            }
        },
    })
})

Now to my issue:

If I choose to edit one of these "ABC" inputs from any of the forms and completely remove the form input's value, I can submit the form without $.validate() recognizing the input is required. Also, I notice a delay when $.validate() does get fired - sometimes a couple of clicks in and out of the input? I'm having a hard time understanding what is triggering the issues.

I can; however, use these same rules ($.validator.setDefaults() and $.validate(rules) to another form that does not have existing values entered with input[name="ABC"]) and $.validate seems to respond correctly.

Finding the Problem:

  • Like I said from the beginning, I am new to these jQuery plugins. I have other forms that I have not discussed that seem to be working as intended (However, these forms do not have values already entered on page load). I am trying to implement "DRY" (Don't Repeat Yourself) code when making $.validator.setDefaults{} and I am wondering is that common for forms to use the same setDefaults or do people create different setDefaults for different class forms? Specifically, forms that initially have values in their input and ones that dont?
  • I read that jQuery validation triggers "lazy", so I was using the onfocusout option for any forms that have inputs with values already entered to make it run sooner. Am I thinking of this wrong with values already in place?
  • When are you suppose to use methods like $(form).validate().destroy() and $(form).validate().resetForm()? Since these inputs are loaded on the page, do I need to reset the form when the "edit" button is clicked?

Sorry for the really long-winded explanation. I hope I have provided enough details for help? I'm hoping it is something obvious that I am missing...Thanks

Franklin
  • 23
  • 5

0 Answers0