0

I am using the jQuery SmartWizard for one of my projects. I have validations in place via the jQuery Validation plugin which appear to be working. The issue is that I want SmartWizard to stop users from navigating to the next step if validation for the current step failed.

The code below seems to work since I can see the Form on step X is invalid console log entry, but the following return false, which supposedly should stop the user from navigating to the next step, seems to be ignored even though validation clearly failed.

I alternatively tried binding the function to a click event for the sw-btn-next button, which is the button thats clicked to proceed to the next step, but this does not seem to work either.

jQuery 3.2.1 // Bootstrap 3.3.7 // SmartWizard 5.1.1 (latest) // jQuery Validation 1.19.3 (latest)

jQuery Validation

// set validation rules for entire form
$('#addNewUser').validate({
    debug: true,
    errorElement: 'span',
    errorClass: 'form-text form-error text-red',
    focusInvalid: false,
    rules: {
        'first_name': {
            required: true,
            minlength: 3
        },
        'last_name': {
            required: true,
            minlength: 3,
        },
        'password': {
            required: true,
            minlength: 5,
            maxlength: 25
        },
        'password_repeat': {
            required: true,
            minlength: 5,
            maxlength: 25,
            equalTo: '#password'
        }
    },
    messages: {
        'first_name': 'Please enter a valid first name'
    }
});

SmartWizard

// ###################################
// # jQuery SmartWizard  plugin
// ###################################
$('#smartwizard').smartWizard({
    selected: 0,        // Initial selected step, 0 = first step
    theme: 'default'   // theme for the wizard, related css need to include for other than default theme

    // when changing steps...
}).on("stepContent", function(e, anchorObject, stepIndex, stepDirection) {

    // check if current step is Step 5 and enable submit button
    $('#newUserSubmit').prop('disabled', stepIndex !== 4);
    console.log('Navigated to stepIndex ' + stepIndex + ' moving in stepDirection ' + stepDirection);

    // check form validation
    var elmForm = $('#form-step-' + stepIndex);
    if (stepDirection == 'forward' && elmForm) {
        if ($('#addNewUser').valid()) {
            console.log('Form on Step ' + stepIndex + ' is valid');
            return true;
        } else {
            console.log('Form on Step ' + stepIndex + ' is invalid');
            return false;
        }
    }

});

// when clicking NEXT button...
$('.sw-btn-next').click(function() {
    console.log('Next button clicked.')
});
Armitage2k
  • 1,164
  • 2
  • 27
  • 59
  • Not sure why it doesn't work. By default, the Validate plugin ignores the parts that are hidden and only validates the step that is show. See: https://stackoverflow.com/q/68561398/594235 Otherwise, I would break it up into separate forms. See: https://stackoverflow.com/q/17748545/594235 – Sparky Nov 17 '21 at 22:40
  • I did try that just now, breaking up one long form into 1 form per step, but `.validate` doesnt seem to work for multiple fields. The linked post is from 8+ years ago and most likely that way of calling validation is not supported anymore. – Armitage2k Nov 18 '21 at 06:54
  • The core of the plugin works the same today as it did 8 years ago. – Sparky Nov 18 '21 at 18:14

2 Answers2

1

After lots of trial and error, I finally fixed the issue by moving the validation check from SmartWizard's stepContent event to the leaveStep event. Please note that the often referenced $('.sw-btn-next').click(function() does not work either, it has to be leaveStep.

// ###################################
// # jQuery SmartWizard  plugin
// ###################################
$('#smartwizard').smartWizard({
    selected: 0, // Initial selected step, 0 = first step
    theme: 'default', // theme for the wizard, related css need to include for other than default theme
    justified: true, // Nav menu justification. true/false
    darkMode: false, // Enable/disable Dark Mode if the theme supports. true/false
    autoAdjustHeight: true, // Automatically adjust content height
    cycleSteps: false, // Allows to cycle the navigation of steps
    backButtonSupport: true, // Enable the back button support
    enableURLhash: false, // Enable selection of the step based on url hash
    // onFinish: onFinishCallback,
    // onCancel: onCancelCallback,
    transition: {
        animation: 'fade', // Effect on navigation, none/fade/slide-horizontal/slide-vertical/slide-swing
        speed: '400', // Transion animation speed
        easing: '' // Transition animation easing. Not supported without a jQuery easing plugin
    },
    toolbarSettings: {
        toolbarPosition: 'bottom', // none, top, bottom, both
        toolbarButtonPosition: 'center', // left, right, center
        showNextButton: true, // show/hide a Next button
        showPreviousButton: true, // show/hide a Previous button
        toolbarExtraButtons: [ // Extra buttons to show on toolbar, array of jQuery input/buttons elements
            $('<button id="newUserSubmit" class="btn btn-sm btn-primary-bordered" disabled><i class="fa fa-check mr-15"></i> Submit</button>')
        ]
    },
    anchorSettings: {
        anchorClickable: false, // Enable/Disable anchor navigation
        enableAllAnchors: false, // Activates all anchors clickable all times
        markDoneStep: false, // Add done state on navigation
        markAllPreviousStepsAsDone: true, // When a step selected by url hash, all previous steps are marked done
        removeDoneStepOnNavigateBack: false, // While navigate back done step after active step will be cleared
        enableAnchorOnDoneStep: true // Enable/Disable the done steps navigation
    },
    keyboardSettings: {
        keyNavigation: false, // Enable/Disable keyboard navigation(left and right keys are used if enabled)
        keyLeft: [37], // Left key code
        keyRight: [39] // Right key code
    },
    lang: { // Language variables for button
        next: 'Next >',
        previous: '< Previous'
    },
    // disabledSteps: [],                       // Array Steps disabled
    // errorSteps: [],                          // Highlight step with errors
    // hiddenSteps: []                          // Hidden steps

    // when changing steps...
}).on("stepContent", function(e, anchorObject, stepIndex, stepDirection) {
    // on step 1, focus on First Name input field
    if (stepIndex == 1) {
        $("#first_name").focus();
    }

    // check if current step is stepIndex 4 and enable submit button
    if (stepIndex == 4) {
        // enable form submit button on last step
        $('#newUserSubmit').prop('disabled', false);
        console.log('StepIndex is 4, enabling submit button');
    } else {
        // disable form submit button on all other steps
        $('#newUserSubmit').prop('disabled', true);
        console.log('StepIndex is not 4, disabling submit button');
    }
});

// Initialize the leaveStep event
$("#smartwizard").on("leaveStep", function(e, anchorObject, stepIndex, nextStepIndex, stepDirection) {
    // navigate to next step
    console.log('Navigated to stepIndex ' + stepIndex + ' moving in stepDirection ' + stepDirection);

    // check if current form step is valid
    var elmForm = $('#form-step-' + stepIndex);
    if (stepDirection == 'forward' && elmForm) {
        if ($('#addNewUser').valid()) {
            console.log('Form on Step ' + stepIndex + ' is valid');
            return true;
        } else {
            console.log('Form on Step ' + stepIndex + ' is invalid');
            return false;
        }
    }
});

Above code works provides a working SmartWizard step-by-step wizard with jQuery Validation for each step by calling validation for the entire form when the user navigates away from the current step. Additionally, the script places an extra Submit button to the wizard which is automatically disable unless the user has reached the final step of the wizard.

There is surprisingly little documentation for this particular use-case, I hope this helps anyone else who experiences issues with SmartWizard & jQuery Validation.

Armitage2k
  • 1,164
  • 2
  • 27
  • 59
0

You can do this by customizing the onLeaveStep callback. This is the piece of code I am currently using to validate each step separately :

$('#smartwizard').on("leaveStep", function(e, anchorObject, stepNumber, nextStepNumber, stepDirection) {

var arrStep = Array(stepNumber.toString())
var elmForm = $("#step-" + stepNumber);

//Loop thru all input fields of the current "partial" form and validate them
var inputs = elmForm.find("input");

if(stepDirection==='forward') {
    //Validate the current form fields
    for (const element of inputs) {
        valid = $('#myForm').validate().element(element);

        if (!valid) {
            return false; //Don't go next step
        }
    }
}
})
b126
  • 544
  • 4
  • 11