4

I am using this Jquery plugin to create a Wizard like interface:

JQuery Bootstrap Smart Wizard

I have 5 steps in the wizard. Step 3 and Step 4 are hidden when the wizard first loads.

  1. When a user selects "Yes" Radio button in Step 2 and then clicks on "Next" button, it should show, enable and go to Step 4 in the Wizard.
  2. When a user selects "No" Radio button in Step 2 and then clicks on "Next" button, it should show, enable and go to Step 3 in the Wizard.

The problem I am facing is, the hidden steps are being shown, on demand, but are showing as disabled. As a result, when I click "Next" on Step 2, the hidden step is shown, but not enabled and thus skips to Step 5.

How do I fix it to achieve the desired behavior?

Here is my code for this:

<div id="smartwizard">
<ul>
    <li><a href="#step-1">Step 1<br /><small>Step 1</small></a></li>
    <li><a href="#step-2">Step 2<br /><small>Step 2</small></a></li>
    <li><a href="#step-3">Step 3<br /><small>Step 3</small></a></li>
    <li><a href="#step-4">Step 4<br /><small>Step 4</small></a></li>
    <li><a href="#step-5">Step 5<br /><small>Step 5</small></a></li>                
</ul>

<div>
    <div id="step-1" class="">
        This is the first step and it should be shown all the time.
    </div>
    <div id="step-2" class="">
        <div>Would you like to add more options?</div>
        <p>
        <input type="radio" name="yes_no" id="step2RadioYes" checked>&nbsp;Yes</input>
        </p>
        <p>
        <input type="radio" name="yes_no" id="step2RadioNo" >&nbsp;No</input>
        </p>
    </div>

    <div id="step-3" class="">
        This step is hidden on load, but should be shown and enabled if I select "No" in Step 2.
    </div>

    <div id="step-4" class="">
        This step is hidden on load, but should be shown and enabled if I select "Yes" in Step 2.
    </div>

    <div id="step-5" class="">
        This step is the final step.
    </div>
</div>

<script>
$('#smartwizard').smartWizard({
            selected: 0,
            theme: 'default',
            transitionEffect:'fade',
            showStepURLhash: false,
            contentCache: false,
            hiddenSteps: [2,3]
    });

$("#smartwizard").on("leaveStep", function(e, anchorObject, stepNumber, stepDirection, stepPosition) {
        if(stepNumber === 1){
           if(document.getElementById('step2RadioYes').checked) {

           // Enable and go to step-4 if Yes is selected
           $('#smartwizard').smartWizard("stepState", [2], "disable");
           $('#smartwizard').smartWizard("stepState", [2], "hide");

           $('#smartwizard').smartWizard("stepState", [3], "enable");
           $('#smartwizard').smartWizard("stepState", [3], "show");
          }
          else if(document.getElementById('step2RadioNo').checked) {

           // Enable and go to step-4 if No is selected
           $('#smartwizard').smartWizard("stepState", [2], "enable");
           $('#smartwizard').smartWizard("stepState", [2], "show");

           $('#smartwizard').smartWizard("stepState", [3], "disable");
           $('#smartwizard').smartWizard("stepState", [3], "hide");
          }
       }
    });    
</script>
Jake
  • 25,479
  • 31
  • 107
  • 168

3 Answers3

5

The leaveStep event doesn't offer the possibility to reset the next/prev step. I may suggest a workaround:

 setTimeout(function() {
    $('#smartwizard').data('smartWizard')._showStep(3); // go to step 3....
 }, 50);

$('#smartwizard').smartWizard({
    selected: 0,
    theme: 'default',
    transitionEffect: 'fade',
    showStepURLhash: false,
    contentCache: false,
    hiddenSteps: [2, 3]
});

$("#smartwizard").on("leaveStep", function (e, anchorObject, stepNumber, stepDirection) {
    $("#smartwizard").data('nextStep', stepNumber + 1);
    if (stepNumber === 1) {
        if (document.getElementById('step2RadioYes').checked) {

            // Enable and go to step-4 if Yes is selected
            $('#smartwizard').smartWizard("stepState", [2], "disable");
            $('#smartwizard').smartWizard("stepState", [2], "hide");

            $('#smartwizard').smartWizard("stepState", [3], "enable");
            $('#smartwizard').smartWizard("stepState", [3], "show");

            setTimeout(function() {
                $('#smartwizard').data('smartWizard')._showStep(3);
            }, 50);

        } else {

            // Enable and go to step-4 if No is selected
            $('#smartwizard').smartWizard("stepState", [2], "enable");
            $('#smartwizard').smartWizard("stepState", [2], "show");

            $('#smartwizard').smartWizard("stepState", [3], "disable");
            $('#smartwizard').smartWizard("stepState", [3], "hide");

            setTimeout(function() {
                $('#smartwizard').data('smartWizard')._showStep(2);
            }, 50);
        }
    }
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://rawgit.com/techlab/SmartWizard/master/dist/css/smart_wizard.min.css">
<script src="https://rawgit.com/techlab/SmartWizard/master/dist/js/jquery.smartWizard.js"></script>

<div id="smartwizard">
    <ul>
        <li><a href="#step-1">Step 1<br/>
            <small>Step 1</small>
        </a></li>
        <li><a href="#step-2">Step 2<br/>
            <small>Step 2</small>
        </a></li>
        <li><a href="#step-3">Step 3<br/>
            <small>Step 3</small>
        </a></li>
        <li><a href="#step-4">Step 4<br/>
            <small>Step 4</small>
        </a></li>
        <li><a href="#step-5">Step 5<br/>
            <small>Step 5</small>
        </a></li>
    </ul>

    <div>
        <div id="step-1" class="">
            This is the first step and it should be shown all the time.
        </div>
        <div id="step-2" class="">
            <div>Would you like to add more options?</div>
            <p>
                <input type="radio" name="yes_no" id="step2RadioYes" checked>&nbsp;Yes</input>
            </p>

            <p>
                <input type="radio" name="yes_no" id="step2RadioNo">&nbsp;No</input>
            </p>
        </div>

        <div id="step-3" class="">
            This step is hidden on load, but should be shown and enabled if I select "No" in Step 2.
        </div>

        <div id="step-4" class="">
            This step is hidden on load, but should be shown and enabled if I select "Yes" in Step 2.
        </div>

        <div id="step-5" class="">
            This step is the final step.
        </div>
    </div>
</div>

A different approach without the setTimeout can be based on remapping the internal methods _showNext / _showPrevious. Perahps it solves the issue but it is also a strong change............

$('#smartwizard').smartWizard({
    selected: 0,
    theme: 'default',
    transitionEffect: 'fade',
    showStepURLhash: false,
    contentCache: false,
    hiddenSteps: [2, 3]
});

function changeDirection(obj, newIdx) {
    if (document.getElementById('step2RadioYes').checked) {
        // Enable and go to step-4 if Yes is selected
        $('#smartwizard').smartWizard("stepState", [2], "disable");
        $('#smartwizard').smartWizard("stepState", [2], "hide");

        $('#smartwizard').smartWizard("stepState", [3], "enable");
        $('#smartwizard').smartWizard("stepState", [3], "show");

        obj._loadStepContent(newIdx);
    } else {
        // Enable and go to step-4 if No is selected
        $('#smartwizard').smartWizard("stepState", [2], "enable");
        $('#smartwizard').smartWizard("stepState", [2], "show");

        $('#smartwizard').smartWizard("stepState", [3], "disable");
        $('#smartwizard').smartWizard("stepState", [3], "hide");

        obj._loadStepContent(newIdx);
    }
}

$("#smartwizard").data('smartWizard')._showNext_orig = $("#smartwizard").data('smartWizard')._showNext;
$("#smartwizard").data('smartWizard')._showNext = function () {
    if (this.current_index === 1) {
        changeDirection(this, 3);
    } else {
        $("#smartwizard").data('smartWizard')._showNext_orig();
    }
    return true;
}
$("#smartwizard").data('smartWizard')._showPrevious_orig = $("#smartwizard").data('smartWizard')._showPrevious;
$("#smartwizard").data('smartWizard')._showPrevious = function () {
    if (this.current_index === 3) {
        changeDirection(this, 1);
    } else {
        $("#smartwizard").data('smartWizard')._showPrevious_orig();
    }
    return true;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://rawgit.com/techlab/SmartWizard/master/dist/css/smart_wizard.min.css">
<script src="https://rawgit.com/techlab/SmartWizard/master/dist/js/jquery.smartWizard.js"></script>

<div id="smartwizard">
    <ul>
        <li><a href="#step-1">Step 1<br/>
            <small>Step 1</small>
        </a></li>
        <li><a href="#step-2">Step 2<br/>
            <small>Step 2</small>
        </a></li>
        <li><a href="#step-3">Step 3<br/>
            <small>Step 3</small>
        </a></li>
        <li><a href="#step-4">Step 4<br/>
            <small>Step 4</small>
        </a></li>
        <li><a href="#step-5">Step 5<br/>
            <small>Step 5</small>
        </a></li>
    </ul>

    <div>
        <div id="step-1" class="">
            This is the first step and it should be shown all the time.
        </div>
        <div id="step-2" class="">
            <div>Would you like to add more options?</div>
            <p>
                <input type="radio" name="yes_no" id="step2RadioYes" checked>&nbsp;Yes</input>
            </p>

            <p>
                <input type="radio" name="yes_no" id="step2RadioNo">&nbsp;No</input>
            </p>
        </div>

        <div id="step-3" class="">
            This step is hidden on load, but should be shown and enabled if I select "No" in Step 2.
        </div>

        <div id="step-4" class="">
            This step is hidden on load, but should be shown and enabled if I select "Yes" in Step 2.
        </div>

        <div id="step-5" class="">
            This step is the final step.
        </div>
    </div>
</div>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61
  • I think that work around seems to work. I will look into it more. Thank you very much. :) – Jake Sep 14 '18 at 18:23
  • Is there a way to not do the settimeout call if I am using the previous button to go to Step 2 from Step 3? – Jake Sep 14 '18 at 18:25
1

Why to wait to click next to enable the Tab? Just add jquery events to the radio button options and once triggered will show and hide the Tabs according to your needs.

$('#step2RadioYes').click(function(){
     $('#smartwizard').smartWizard("stepState", [2], "disable");
     $('#smartwizard').smartWizard("stepState", [2], "hide");
     $('#smartwizard').smartWizard("stepState", [3], "enable");
     $('#smartwizard').smartWizard("stepState", [3], "show");
    
})
$('#step2RadioNo').click(function(){
     $('#smartwizard').smartWizard("stepState", [3], "disable");
     $('#smartwizard').smartWizard("stepState", [3], "hide");
     $('#smartwizard').smartWizard("stepState", [2], "enable");
     $('#smartwizard').smartWizard("stepState", [2], "show");
    
})
lisandro
  • 454
  • 4
  • 12
0

Instead of triggering the show/hide on the move next, another idea would be to trigger it off of the changing of the radio buttons directly. That way the correct next step exists already when move next is clicked.

$('#step2RadioYes').on('change', function () {
    if ($(this).is(':checked')) {
        $('#smartwizard').smartWizard("stepState", [2], "disable");
        $('#smartwizard').smartWizard("stepState", [2], "hide");

        $('#smartwizard').smartWizard("stepState", [3], "enable");
        $('#smartwizard').smartWizard("stepState", [3], "show");
    } else{
        $('#smartwizard').smartWizard("stepState", [2], "enable");
        $('#smartwizard').smartWizard("stepState", [2], "show");

        $('#smartwizard').smartWizard("stepState", [3], "disable");
        $('#smartwizard').smartWizard("stepState", [3], "hide");
    }
});



$('#step2RadioYes').on('change', function () {
    if ($(this).is(':checked')) {
        $('#smartwizard').smartWizard("stepState", [2], "enable");
        $('#smartwizard').smartWizard("stepState", [2], "show");

        $('#smartwizard').smartWizard("stepState", [3], "disable");
        $('#smartwizard').smartWizard("stepState", [3], "hide");
    }else{
        $('#smartwizard').smartWizard("stepState", [2], "enable");
        $('#smartwizard').smartWizard("stepState", [2], "hide");

        $('#smartwizard').smartWizard("stepState", [3], "enablex");
        $('#smartwizard').smartWizard("stepState", [3], "show");
    }
});
Solmead
  • 4,158
  • 2
  • 26
  • 30
  • Please edit your answer to include some explanation of your solution. This will make your answer more useful to others and make it more likely for it to be upvoted :) – Das_Geek Oct 03 '19 at 17:52