javascriptjqueryvalidationbootstrap-4jquery-validation-engine

JQuery Validation Form inside a Bootstrap 4 Modal with Tabs won't submit


I'm having an issue with JQuery Validation inside a modal with tabs.

On the Sign in Tab, when I click on the Login button the validation errors pop up as intended:

Signin Tab Works

PROBLEM 1

But on the New Account tab, when I click on the Get Started Button. Nothing Happens. The Submit Handler is not triggering, and the validation error messages only appear if I type something.
Problem 1 Get Started Not submitting

PROBLEM 2

When I click on the Forgot Password Link, it takes me to another tab in the same modal. But when I press the "Reset Password" Button I get another error:

{"error":"key missing: title"}

What am I doing wrong? Is it possible to have 3 submit handlers working properly for the three different tabs in the modal?

Use this fiddle to troubleshoot it: https://jsfiddle.net/h6onufs5/

JS:

(function(){
    //Login/Signup modal window - by CodyHouse.co
    function ModalSignin( element ) {
        this.element = element;
        this.blocks = this.element.getElementsByClassName('js-signin-modal-block');
        this.switchers = this.element.getElementsByClassName('js-signin-modal-switcher')[0].getElementsByTagName('a'); 
        this.triggers = document.getElementsByClassName('js-signin-modal-trigger');
        this.hidePassword = this.element.getElementsByClassName('js-hide-password');
        this.init();
    };

    ModalSignin.prototype.init = function() {
        var self = this;
        //open modal/switch form
        for(var i =0; i < this.triggers.length; i++) {
            (function(i){
                self.triggers[i].addEventListener('click', function(event){
                    if( event.target.hasAttribute('data-signin') ) {
                        event.preventDefault();
                        self.showSigninForm(event.target.getAttribute('data-signin'));
                    }
                });
            })(i);
        }

        //close modal
        this.element.addEventListener('click', function(event){
            if( hasClass(event.target, 'js-signin-modal') || hasClass(event.target, 'js-close') ) {
                event.preventDefault();
                removeClass(self.element, 'cd-signin-modal--is-visible');
            }
        });
        //close modal when clicking the esc keyboard button
        document.addEventListener('keydown', function(event){
            (event.which=='27') && removeClass(self.element, 'cd-signin-modal--is-visible');
        });

        //hide/show password
        for(var i =0; i < this.hidePassword.length; i++) {
            (function(i){
                self.hidePassword[i].addEventListener('click', function(event){
                    self.togglePassword(self.hidePassword[i]);
                });
            })(i);
        } 

        //IMPORTANT - REMOVE THIS - it's just to show/hide error messages in the demo
        this.blocks[0].getElementsByTagName('form')[0].addEventListener('submit', function(event){
            event.preventDefault();
            self.toggleError(document.getElementById('signin-email'), true);
        });
        this.blocks[1].getElementsByTagName('form')[0].addEventListener('submit', function(event){
            event.preventDefault();
            self.toggleError(document.getElementById('signup-username'), true);
        });
    };

    ModalSignin.prototype.togglePassword = function(target) {
        var password = target.previousElementSibling;
        ( 'password' == password.getAttribute('type') ) ? password.setAttribute('type', 'text') : password.setAttribute('type', 'password');
        target.textContent = ( 'Hide' == target.textContent ) ? 'Show' : 'Hide';
        putCursorAtEnd(password);
    }

    ModalSignin.prototype.showSigninForm = function(type) {
        // show modal if not visible
        !hasClass(this.element, 'cd-signin-modal--is-visible') && addClass(this.element, 'cd-signin-modal--is-visible');
        // show selected form
        for( var i=0; i < this.blocks.length; i++ ) {
            this.blocks[i].getAttribute('data-type') == type ? addClass(this.blocks[i], 'cd-signin-modal__block--is-selected') : removeClass(this.blocks[i], 'cd-signin-modal__block--is-selected');
        }
        //update switcher appearance
        var switcherType = (type == 'signup') ? 'signup' : 'login';
        for( var i=0; i < this.switchers.length; i++ ) {
            this.switchers[i].getAttribute('data-type') == switcherType ? addClass(this.switchers[i], 'cd-selected') : removeClass(this.switchers[i], 'cd-selected');
        } 
    };

    ModalSignin.prototype.toggleError = function(input, bool) {
        // used to show error messages in the form
        toggleClass(input, 'cd-signin-modal__input--has-error', bool);
        toggleClass(input.nextElementSibling, 'cd-signin-modal__error--is-visible', bool);
    }

    var signinModal = document.getElementsByClassName("js-signin-modal")[0];
    if( signinModal ) {
        new ModalSignin(signinModal);
    }

    // toggle main navigation on mobile
    var mainNav = document.getElementsByClassName('js-main-nav')[0];
    if(mainNav) {
        mainNav.addEventListener('click', function(event){
            if( hasClass(event.target, 'js-main-nav') ){
                var navList = mainNav.getElementsByTagName('ul')[0];
                toggleClass(navList, 'cd-main-nav__list--is-visible', !hasClass(navList, 'cd-main-nav__list--is-visible'));
            } 
        });
    }

    //class manipulations - needed if classList is not supported
    function hasClass(el, className) {
        if (el.classList) return el.classList.contains(className);
        else return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
    }
    function addClass(el, className) {
        var classList = className.split(' ');
        if (el.classList) el.classList.add(classList[0]);
        else if (!hasClass(el, classList[0])) el.className += " " + classList[0];
        if (classList.length > 1) addClass(el, classList.slice(1).join(' '));
    }
    function removeClass(el, className) {
        var classList = className.split(' ');
        if (el.classList) el.classList.remove(classList[0]);    
        else if(hasClass(el, classList[0])) {
            var reg = new RegExp('(\\s|^)' + classList[0] + '(\\s|$)');
            el.className=el.className.replace(reg, ' ');
        }
        if (classList.length > 1) removeClass(el, classList.slice(1).join(' '));
    }
    function toggleClass(el, className, bool) {
        if(bool) addClass(el, className);
        else removeClass(el, className);
    }

    //credits http://css-tricks.com/snippets/jquery/move-cursor-to-end-of-textarea-or-input/
    function putCursorAtEnd(el) {
        if (el.setSelectionRange) {
            var len = el.value.length * 2;
            el.focus();
            el.setSelectionRange(len, len);
        } else {
            el.value = el.value;
        }
    };
})();



$('#login-form').validate ({

        // validation rules for registration form
    errorClass: "error-class",
    validClass: "valid-class",
    errorElement: 'div',
    errorPlacement: function(error, element) {
        if(element.parent('.input-group').length) {
            error.insertAfter(element.parent());
        } else {
            error.insertAfter(element);
        }
    },
    onError : function(){
        $('.input-group.error-class').find('.help-block.form-error').each(function() {
          $(this).closest('.form-control').addClass('error-class').append($(this));
        });
    },

        rules: {
            username: {
                required: true,
                minlength: 3,
                maxlength: 40
            },

          password: {
                required: true,
                minlength: 7,
                maxlength: 20
            }
            },

        messages: {
            username: {
                required: "Please enter your username or email address",
                minlength: "Usernames can't be shorter than three characters",
                maxlength: "Usernames or emails must be shorter than forty characters."
            },
                       password: {
                required: "Please enter your password",
                minlength: "Passwords can't be shorter than seven characters",
                maxlength: "Passwords must be shorter than forty characters."
            },

                highlight: function(element, errorClass) {
        $(element).removeClass(errorClass);
    }    
        },

  submitHandler: function() {  
            $('#noenter').show();   

        }

    });


    $("#signup-form").validate ({

        // validation rules for registration formd
    errorClass: "error-class",
    validClass: "valid-class",
    errorElement: 'div',
    errorPlacement: function(error, element) {
        if(element.parent('.input-group').length) {
            error.insertAfter(element.parent());
        } else {
            error.insertAfter(element);
        }
    },
    onError : function(){
        $('.input-group.error-class').find('.help-block.form-error').each(function() {
          $(this).closest('.form-group').addClass('error-class').append($(this));
        });
    },


        messages: {
            email: {
                required: "Please enter your email address",

            },


                highlight: function(element, errorClass) {
        $(element).removeClass(errorClass);
    }    
        }

    });


   $("#password-form").validate ({

        // validation rules for registration formd
    errorClass: "error-class",
    validClass: "valid-class",
    errorElement: 'div',
    errorPlacement: function(error, element) {
        if(element.parent('.input-group').length) {
            error.insertAfter(element.parent());
        } else {
            error.insertAfter(element);
        }
    },
    onError : function(){
        $('.input-group.error-class').find('.help-block.form-error').each(function() {
          $(this).closest('.form-group').addClass('error-class').append($(this));
        });
    },


        messages: {
            email: {
                required: "Please enter your email address",

            },


                highlight: function(element, errorClass) {
        $(element).removeClass(errorClass);
    }    
        }

    });

FOR HTML CLICK ON THE FIDDLE. Please let me know if it is possible to fix these problem. Thank you..


Solution

  • In the validator for the signup-form, you should add the rules for the email input like:

    rules: {
        email: {email:true, required:true}
      }
    

    I added it in this fiddle and it works: https://jsfiddle.net/h6onufs5/4/

    Hope this helps