skip to Main Content

I have a multi-step form that uses Bootstrap nav-pills.
Clicking through the buttons works as expected, as well as clicking through the separate buttons. However, I want to disable them so users won’t be able to go to the other pages without completing the displayed form fields first. The content change will be triggered using a different button.

I tried adding the disable class and the disabled attribute on the buttons, but doing so made the functionality(showing the correct tab-pane and adding active class to the button) not work.
enter image description here

My current javascript code:

if (document.querySelectorAll(".form-steps"))
Array.from(document.querySelectorAll(".form-steps")).forEach(function (form) {

    // next tab
    if (form.querySelectorAll(".nexttab")){
        Array.from(form.querySelectorAll(".nexttab")).forEach(function (nextButton) {
            var tabEl = form.querySelectorAll('button[data-bs-toggle="pill"]');
            Array.from(tabEl).forEach(function (item) {
                item.addEventListener('show.bs.tab', function (event) {
                    event.target.classList.add('done');
                });
            });
            nextButton.addEventListener("click", function () {
                form.classList.add('was-validated');
                var is_required = true;
                form.querySelectorAll(".tab-pane.show .form-control").forEach(function(elem){
                    if(elem.hasAttribute('required') == true && elem.value.length == 0){
                        is_required = false;
                    }
                });
                console.log(is_required);
                if(is_required == true){
                    var nextTab = nextButton.getAttribute('data-nexttab');
                    var nextActive = $('#' + nextTab).data('bs-target');
                    document.getElementById(nextTab).click();
                    Array.from(form.querySelectorAll(".tab-pane")).forEach(function (nextTabPane) {
                        nextTabPane.classList.remove('active');
                        nextTabPane.classList.remove('show');
                    });
                    $(nextActive).addClass('active show');
                    form.classList.remove('was-validated');
                }
            })
        });
    }

    //Pervies tab
    if (form.querySelectorAll(".previestab"))
        Array.from(form.querySelectorAll(".previestab")).forEach(function (prevButton) {

            prevButton.addEventListener("click", function () {
                var prevTab = prevButton.getAttribute('data-previous');
                var totalDone = prevButton.closest("form").querySelectorAll(".custom-nav .done").length;
                for (var i = totalDone - 1; i < totalDone; i++) {
                    (prevButton.closest("form").querySelectorAll(".custom-nav .done")[i]) ? prevButton.closest("form").querySelectorAll(".custom-nav .done")[i].classList.remove('done'): '';
                }
                document.getElementById(prevTab).click();
            });
        });

    // Step number click
    var tabButtons = form.querySelectorAll('button[data-bs-toggle="pill"]');
    if (tabButtons)
        Array.from(tabButtons).forEach(function (button, i) {
            button.setAttribute("data-position", i);
            button.addEventListener("click", function () {
                form.classList.remove('was-validated');
       
                var getProgressBar = button.getAttribute("data-progressbar");
                if (getProgressBar) {
                    var totalLength = document.getElementById("custom-progress-bar").querySelectorAll("li").length - 1;
                    var current = i;
                    var percent = (current / totalLength) * 100;
                    document.getElementById("custom-progress-bar").querySelector('.progress-bar').style.width = percent + "%";
                }
                (form.querySelectorAll(".custom-nav .done").length > 0) ?
                Array.from(form.querySelectorAll(".custom-nav .done")).forEach(function (doneTab) {
                    doneTab.classList.remove('done');
                }): '';
                for (var j = 0; j <= i; j++) {
                    tabButtons[j].classList.contains('active') ? tabButtons[j].classList.remove('done') : tabButtons[j].classList.add('done');
                }
            });
        });
});

Here’s a code snippet of my HTML(I only included two tab-pane because it’s too long for 4 tabs.):

<form class="vertical-navs-step">
<div class="row gy-5">
    <div class="col-lg-3">
        <div class="nav flex-column custom-nav nav-pills" role="tablist" aria-orientation="vertical">
            <button class="nav-link active" id="v-pills-personal-details-tab" data-bs-toggle="pill" data-bs-target="#v-pills-personal-details" type="button" role="tab" aria-controls="v-pills-personal-details" aria-selected="true" data-position="0">
                <span class="step-title me-2">
                    <i class="ri-close-circle-fill step-icon me-2"></i> Section 1
                </span>
            </button>
            <button class="nav-link" id="v-pills-section-2-tab" data-bs-toggle="pill" data-bs-target="#v-pills-section-2" type="button" role="tab" aria-controls="v-pills-section-2" aria-selected="false" data-position="1" tabindex="-1">
                <span class="step-title me-2">
                    <i class="ri-close-circle-fill step-icon me-2"></i> Section 2
                </span>
            </button>
            <button class="nav-link" id="v-pills-section-3-tab" data-bs-toggle="pill" data-bs-target="#v-pills-section-3" type="button" role="tab" aria-controls="v-pills-section-3" aria-selected="false" data-position="2" tabindex="-1">
                <span class="step-title me-2">
                    <i class="ri-close-circle-fill step-icon me-2"></i> Section 3
                </span>
            </button>
            <button class="nav-link" id="v-pills-finish-tab" data-bs-toggle="pill" data-bs-target="#v-pills-finish" type="button" role="tab" aria-controls="v-pills-finish" aria-selected="false" data-position="3" tabindex="-1">
                <span class="step-title me-2">
                    <i class="ri-close-circle-fill step-icon me-2"></i> Section 4
                </span>
            </button>
        </div>
        <!-- end nav -->
    </div> <!-- end col-->
    <div class="col-lg-9">
        <div class="px-lg-4">
            <div class="tab-content">
                <div class="tab-pane fade active show" id="v-pills-personal-details" role="tabpanel" aria-labelledby="v-pills-personal-details-tab">
                    <div>
                        <h5>Section 1</h5>
                        <p class="text-muted">Fill all information below</p>
                    </div>
                    <div>
                        <div class="row g-3">
                            <div class="col-sm-6">
                                <label for="firstnameInput" class="form-label">First name<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="firstnameInput" name="first_name" placeholder="Enter your firstname" value="<?php echo $user['first_name']; ?>" required/>
                                <div data-lastpass-icon-root="" style="position: relative !important; height: 0px !important; width: 0px !important; float: left !important;"></div></div>

                            <div class="col-sm-6">
                                <label for="lastnameInput" class="form-label">Last name<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="lastnameInput" name="last_name" placeholder="Enter your lastname" value="<?php echo $user['last_name']; ?>" required/>
                            </div>
                            <div class="col-sm-6">
                                <label for="phonenumberInput" class="form-label">Phone Number<span class="text-danger">*</span></label>
                                <input type="tel" class="form-control" id="phonenumberInput" name="phonenumberInput" placeholder="Enter your phone number" value="<?php echo $user['full_phone']; ?>" required/>
                                <input type="hidden" name="full_phone">
                                <div class="invalid-feedback">Please enter your mobile number</div>
                            </div>
                            <div class="col-sm-6">
                                <label for="emailInput" class="form-label">Email Address<span class="text-danger">*</span></label>
                                <input type="email" class="form-control" id="emailInput" name="emailInput" placeholder="Enter your email" value="<?php echo auth()->user()->getEmail(); ?>" required/>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="websiteInput1" class="form-label">Website <span class="text-muted">(Optional)</span></label>
                                <input type="text" class="form-control" id="websiteInput1" name="websiteInput1" placeholder="www.example.com" value="" />
                            </div>
                            <div class="col-sm-6">
                                <label for="companyInput" class="form-label">Company<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="companyInput" name="companyInput" placeholder="Company" value="<?php echo $user['company_name']; ?>" required/>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="contactPersonInput" class="form-label">Primary Contact Person<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="contactPersonInput" name="contactPersonInput" placeholder="Primary Contact Person" value="" required/>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="superviseVAInput" class="form-label">Name of Person Who Will Supervise Your Virtual Assistant<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="superviseVAInput" name="superviseVAInput" placeholder="Who will Supervise" value="" required/>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="cityInput" class="form-label">City<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="cityInput" name="cityInput" placeholder="Enter City" required/>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="stateInput" class="form-label">State<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="stateInput" name="stateInput" placeholder="Enter State" value="" required/>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="countryInput" class="form-label">Country<span class="text-danger">*</span></label>
                                <select class="js-example-basic-single form-control" id="countryInput" name="countryInput" required/>
                                    <option></option>
                                    <?php foreach($countries AS $country): ?>
                                    <option value="<?php echo $country['country_name']; ?>"><?php echo $country['country_name']; ?></option>
                                    <?php endforeach; ?>
                                </select>
                            </div>
                            <!--end col-->
                            <div class="col-sm-6">
                                <label for="zipcodeInput" class="form-label">Zip Code<span class="text-danger">*</span></label>
                                <input type="text" class="form-control" minlength="5" maxlength="6" id="zipcodeInput" name="zipcodeInput" value="" placeholder="Enter zipcode" required/>
                            </div>
                            <!--end col-->
                        </div>
                    </div>

                    <div class="d-flex align-items-start gap-3 mt-4">
                        <button type="button" class="btn btn-success btn-label right ms-auto nexttab" data-nexttab="v-pills-section-2-tab"><i class="ri-arrow-right-line label-icon align-middle fs-16 ms-2"></i>Go to Section 2</button>
                    </div>
                </div>
                <!-- end tab pane -->
                <div class="tab-pane fade" id="v-pills-section-2" role="tabpanel" aria-labelledby="v-pills-section-2-tab">
                    <div>
                        <h5>Section 2</h5>
                        <p class="text-muted">Fill all information below</p>
                    </div>

                    <div>
                        <div class="row g-3">
                            <div class="col-sm-12">
                                <div class="mb-3 pb-2">
                                    <label for="businessdescTextarea" class="form-label">Business Description <span class="text-muted">(Optional)</span></label>
                                    <textarea class="form-control" id="businessdescTextarea" name="businessdesc" placeholder="Enter your description" rows="3" required></textarea>
                                </div>
                            </div>
                            <!--end col-->

                            <div class="col-sm-6">
                                <label for="industryInput" class="form-label">What Industry Is Your Business In? <span class="text-muted">(Optional)</span></label>
                                <input type="text" class="form-control" id="industryInput" name="industryInput" placeholder="Enter business industry">
                            </div>
                            <div class="col-sm-6">
                                <label for="industryInput" class="form-label">Have you ever used a Virtual Assistant before? <span class="text-muted">(Optional)</span></label>
                                <div class="form-check">
                                    <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioYes" value="yes">
                                    <label class="form-check-label" for="flexRadioYes">Yes</label>
                                </div>

                                <div class="form-check">
                                    <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioNo" value="no">
                                    <label class="form-check-label" for="flexRadioNo">No</label>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="d-flex align-items-start gap-3 mt-4">
                        <button type="button" class="btn btn-light btn-label previestab" data-previous="v-pills-personal-details-tab"><i class="ri-arrow-left-line label-icon align-middle fs-16 me-2"></i> Back to Section 1</button>
                        <button type="button" class="btn btn-success btn-label right ms-auto nexttab" data-nexttab="v-pills-section-3-tab"><i class="ri-arrow-right-line label-icon align-middle fs-16 ms-2"></i>Go to Section 3</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</form>

And the last button will submit the form after all the validation is met.

2

Answers


  1. have you tried adding pe-none class or a custom css pointer-events: none;?

    Login or Signup to reply.
  2. Adding the disabled attribute works in principle, as demonstrated below. The trick is to remove the disabled attribute on the buttons as the user progresses through the form. Eg: $('#' + nextTab).attr("disabled", false);

        // next tab
        if (document.querySelectorAll(".nexttab")){
            Array.from(document.querySelectorAll(".nexttab")).forEach(function (nextButton) {
                var tabEl = document.querySelectorAll('button[data-bs-toggle="pill"]');
                Array.from(tabEl).forEach(function (item) {
                    item.addEventListener('show.bs.tab', function (event) {
                        event.target.classList.add('done');
                    });
                });
                nextButton.addEventListener("click", function () {
                /*Removed -- not relevant to issue
                    document.classList.add('was-validated');
                    var is_required = true;
                    document.querySelectorAll(".tab-pane.show .form-control").forEach(function(elem){
                        if(elem.hasAttribute('required') == true && elem.value.length == 0){
                            is_required = false;
                        }
                    }); 
                    console.log(is_required);
                    if(is_required == true){*/
                        var nextTab = nextButton.getAttribute('data-nexttab');
                        var nextActive = $('#' + nextTab).data('bs-target');
                        //Re enable the button for the new section
                        $('#' + nextTab).attr("disabled", false);
                        document.getElementById(nextTab).click();
                        Array.from(document.querySelectorAll(".tab-pane")).forEach(function (nextTabPane) {
                            nextTabPane.classList.remove('active');
                            nextTabPane.classList.remove('show');
                        });
                        $(nextActive).addClass('active show');
                     //   form.classList.remove('was-validated');
                  //  }
                })
            });
        }
    /*Just for demo*/
    button[disabled] {color: #ddd !important;}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
    <div class="container">
      <form class="vertical-navs-step">
        <div class="row gy-5">
          <div class="col-lg-3">
            <div class="nav flex-column custom-nav nav-pills" role="tablist" aria-orientation="vertical">
              <button class="nav-link active" id="v-pills-personal-details-tab" data-bs-toggle="pill" data-bs-target="#v-pills-personal-details" type="button" role="tab" aria-controls="v-pills-personal-details" aria-selected="true" data-position="0">
                    <span class="step-title me-2">
                        <i class="ri-close-circle-fill step-icon me-2"></i> Section 1
                    </span>
                </button>
              <button class="nav-link" id="v-pills-section-2-tab" data-bs-toggle="pill" data-bs-target="#v-pills-section-2" type="button" role="tab" aria-controls="v-pills-section-2" aria-selected="false" data-position="1" tabindex="-1" disabled>
                    <span class="step-title me-2">
                        <i class="ri-close-circle-fill step-icon me-2"></i> Section 2
                    </span>
                </button>
              <button class="nav-link" id="v-pills-section-3-tab" data-bs-toggle="pill" data-bs-target="#v-pills-section-3" type="button" role="tab" aria-controls="v-pills-section-3" aria-selected="false" data-position="2" tabindex="-1" disabled>
                    <span class="step-title me-2">
                        <i class="ri-close-circle-fill step-icon me-2"></i> Section 3
                    </span>
                </button>
              <button class="nav-link" id="v-pills-finish-tab" data-bs-toggle="pill" data-bs-target="#v-pills-finish" type="button" role="tab" aria-controls="v-pills-finish" aria-selected="false" data-position="3" tabindex="-1" disabled>
                    <span class="step-title me-2">
                        <i class="ri-close-circle-fill step-icon me-2"></i> Section 4
                    </span>
                </button>
            </div>
            <!-- end nav -->
          </div>
          <!-- end col-->
          <div class="col-lg-9">
            <div class="px-lg-4">
              <div class="tab-content">
                <div class="tab-pane fade active show" id="v-pills-personal-details" role="tabpanel" aria-labelledby="v-pills-personal-details-tab">
                  <div>
                    <h5>Section 1</h5>
                    <p class="text-muted">Fill all information below</p>
                  </div>
    
                  <div class="d-flex align-items-start gap-3 mt-4">
                    <button type="button" class="btn btn-success btn-label right ms-auto nexttab" data-nexttab="v-pills-section-2-tab"><i class="ri-arrow-right-line label-icon align-middle fs-16 ms-2"></i>Go to Section 2</button>
                  </div>
                </div>
                <!-- end tab pane -->
                <div class="tab-pane fade" id="v-pills-section-2" role="tabpanel" aria-labelledby="v-pills-section-2-tab">
                  <div>
                    <h5>Section 2</h5>
                    <p class="text-muted">Fill all information below</p>
                  </div>
    
    
                  <div class="d-flex align-items-start gap-3 mt-4">
                    <button type="button" class="btn btn-light btn-label previestab" data-previous="v-pills-personal-details-tab"><i class="ri-arrow-left-line label-icon align-middle fs-16 me-2"></i> Back to Section 1</button>
                    <button type="button" class="btn btn-success btn-label right ms-auto nexttab" data-nexttab="v-pills-section-3-tab"><i class="ri-arrow-right-line label-icon align-middle fs-16 ms-2"></i>Go to Section 3</button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </form>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search