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.
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
have you tried adding
pe-none
class or a custom csspointer-events: none;
?Adding the
disabled
attribute works in principle, as demonstrated below. The trick is to remove thedisabled
attribute on the buttons as the user progresses through the form. Eg:$('#' + nextTab).attr("disabled", false);