Multi Step Form Wizard jQuery Validation

Websolutionstuff | Jan-30-2023 | Categories : jQuery Bootstrap

In this article, we will see multi step form wizard jquery validation. Here, we will learn jquery validation for multi step form wizard. Sometimes we required multi step form to register user details, personal details, job details, etc. But we required validation for specific form fields. So, we will validate multi step form using validate js.

So, let's see the jquery multi step form wizard with validation, multi step form validation javascript, multi step form using jquery, validate multi step form using jquery, and jquery validation plugin.

Add HTML:

<section class="multi-step-form">

	<h4>Multi Step Form Wizard jQuery Validation - Websolutionstuff</h4>

	<div class="steps">
		<button class="active" type="button" disabled>Step One</button> |
		<button type="button" disabled>Step Two</button> |
		<button type="button" disabled>Step Three</button>
	</div>

	<form action="#" method="post">

		<fieldset aria-label="Step One" tabindex="-1" id="step-1">
			<h2>Step One</h2>
			<p>
				<label for="first-name">First Name</label>
				<input class="form-control" type="text" name="first-name" id="first-name" required>
			</p>
			<p>
				<label for="last-name">Last Name</label>
				<input class="form-control" type="text" name="last-name" id="last-name" required>
			</p>
			<p>
				<button class="btn btn-default btn-next" type="button" aria-controls="step-2">Next</button>
			</p>
		</fieldset>

		<fieldset aria-label="Step Two" tabindex="-1" id="step-2">
			<h2>Step Two</h2>
			<p>
				<label for="email-address">Email Address</label>
				<input class="form-control" type="email" name="email-address" id="email-address" required>
			</p>
			<p>
				<label for="phone-number">Phone Number <span class="optional">(optional)</span></label>
				<input class="form-control" type="tel" name="phone-number" id="phone-number">
			</p>
			<p>
				<button class="btn btn-default btn-prev" type="button" aria-controls="step-1">Previous</button>
				<button class="btn btn-default btn-next" type="button" aria-controls="step-3">Next</button>
			</p>
		</fieldset>

		<fieldset aria-label="Step Three" tabindex="-1" id="step-3">
			<h2>Step Three</h2>
			<p>
				<label for="message"></label>
				<textarea class="form-control" rows="3" name="message" id="message" required></textarea>
			</p>
			<p>
				<button class="btn btn-success" type="submit">Submit</button>
				<button class="btn btn-default btn-edit" type="button">Edit</button>
				<button class="btn btn-danger" type="reset">Start Over</button>
			</p>
		</fieldset>

	</form>
</section>

 

Add CSS:

<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet" type="text/css">
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/cosmo/bootstrap.min.css" rel="stylesheet" type="text/css">
.no-js .multi-step-form fieldset button, .multi-step-form.edit-form fieldset button, .no-js .multi-step-form h2, .multi-step-form.edit-form h2 {
	 display: none !important;
}
 .no-js .multi-step-form fieldset, .multi-step-form.edit-form fieldset {
	 display: block !important;
}
 .no-js .multi-step-form [type="submit"], .multi-step-form.edit-form [type="submit"], .no-js .multi-step-form [type="reset"], .multi-step-form.edit-form [type="reset"] {
	 display: inline-block !important;
}
 .no-js .multi-step-form .steps, .multi-step-form.edit-form .steps {
	 display: none;
}
 .multi-step-form fieldset {
	 display: none;
}
 .multi-step-form fieldset:first-of-type {
	 display: block;
}
 .multi-step-form fieldset.hidden {
	 display: none;
}
 .multi-step-form fieldset.visible {
	 display: block;
}
 .multi-step-form .steps button {
	 border: 0;
}
 .multi-step-form .steps [disabled] {
	 background: none;
}
 .multi-step-form .steps .active {
	 background: #eee;
}
 body {
	 padding: 1em;
	 max-width: 35em;
	 margin: 0 auto;
}
 .error {
	 color: red;
}
 label .optional {
	 font-weight: normal;
	 font-size: 90%;
}
h4{
	font-weight:600;
	font-size:18px;
	margin-bottom:30px;
}

 

Add jQuery:

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.0/jquery.validate.min.js"></script>
<script>
document.documentElement.className = document.documentElement.className.replace("no-js","js");
</script>
var app = {

	init: function(){
		this.cacheDOM();
		this.setupAria();
		this.nextButton();
		this.prevButton();
		this.validateForm();
		this.startOver();
		this.editForm();
		this.killEnterKey();
		this.handleStepClicks();
	},

	cacheDOM: function(){
		if($(".multi-step-form").size() === 0){ return; }
		this.$formParent = $(".multi-step-form");
		this.$form = this.$formParent.find("form");
		this.$formStepParents = this.$form.find("fieldset"),

		this.$nextButton = this.$form.find(".btn-next");
		this.$prevButton = this.$form.find(".btn-prev");
		this.$editButton = this.$form.find(".btn-edit");
		this.$resetButton = this.$form.find("[type='reset']");

		this.$stepsParent = $(".steps");
		this.$steps = this.$stepsParent.find("button");
	},

	htmlClasses: {
		activeClass: "active",
		hiddenClass: "hidden",
		visibleClass: "visible",
		editFormClass: "edit-form",
		animatedVisibleClass: "animated fadeIn",
		animatedHiddenClass: "animated fadeOut",
		animatingClass: "animating"
	},

	setupAria: function(){

		// set first parent to visible
		this.$formStepParents.eq(0).attr("aria-hidden",false);

		// set all other parents to hidden
		this.$formStepParents.not(":first").attr("aria-hidden",true);

		// handle aria-expanded on next/prev buttons
		app.handleAriaExpanded();

	},

	nextButton: function(){

		this.$nextButton.on("click", function(e){

			e.preventDefault();

			// grab current step and next step parent
			var $this = $(this),
					currentParent = $this.closest("fieldset"),
					nextParent = currentParent.next();

					// if the form is valid hide current step
					// trigger next step
					if(app.checkForValidForm()){
						currentParent.removeClass(app.htmlClasses.visibleClass);
						app.showNextStep(currentParent, nextParent);
					}

		});
	},

	prevButton: function(){

		this.$prevButton.on("click", function(e){

			e.preventDefault();

			// grab current step parent and previous parent
			var $this = $(this),
					currentParent = $(this).closest("fieldset"),
					prevParent = currentParent.prev();

					// hide current step and show previous step
					// no need to validate form here
					currentParent.removeClass(app.htmlClasses.visibleClass);
					app.showPrevStep(currentParent, prevParent);

		});
	},

	showNextStep: function(currentParent,nextParent){

		// hide previous parent
		currentParent
			.addClass(app.htmlClasses.hiddenClass)
			.attr("aria-hidden",true);

		// show next parent
		nextParent
			.removeClass(app.htmlClasses.hiddenClass)
			.addClass(app.htmlClasses.visibleClass)
			.attr("aria-hidden",false);

		// focus first input on next parent
		nextParent.focus();

		// activate appropriate step
		app.handleState(nextParent.index());

		// handle aria-expanded on next/prev buttons
		app.handleAriaExpanded();

	},

	showPrevStep: function(currentParent,prevParent){

		// hide previous parent
		currentParent
			.addClass(app.htmlClasses.hiddenClass)
			.attr("aria-hidden",true);

		// show next parent
		prevParent
			.removeClass(app.htmlClasses.hiddenClass)
			.addClass(app.htmlClasses.visibleClass)
			.attr("aria-hidden",false);

		// send focus to first input on next parent
		prevParent.focus();

		// activate appropriate step
		app.handleState(prevParent.index());

		// handle aria-expanded on next/prev buttons
		app.handleAriaExpanded();

	},

	handleAriaExpanded: function(){

		/*
			Loop thru each next/prev button
			Check to see if the parent it conrols is visible
			Handle aria-expanded on buttons
		*/
		$.each(this.$nextButton, function(idx,item){
			var controls = $(item).attr("aria-controls");
			if($("#"+controls).attr("aria-hidden") == "true"){
				$(item).attr("aria-expanded",false);
			}else{
				$(item).attr("aria-expanded",true);
			}
		});

		$.each(this.$prevButton, function(idx,item){
			var controls = $(item).attr("aria-controls");
			if($("#"+controls).attr("aria-hidden") == "true"){
				$(item).attr("aria-expanded",false);
			}else{
				$(item).attr("aria-expanded",true);
			}
		});

	},

	validateForm: function(){
		// jquery validate form validation
		this.$form.validate({
			ignore: ":hidden", // any children of hidden desc are ignored
			errorElement: "span", // wrap error elements in span not label
			invalidHandler: function(event, validator){ // add aria-invalid to el with error
				$.each(validator.errorList, function(idx,item){
					if(idx === 0){
						$(item.element).focus(); // send focus to first el with error
					}
					$(item.element).attr("aria-invalid",true); // add invalid aria
				})
			},
			submitHandler: function(form) {
				alert("form submitted!");
		    // form.submit();
		  }
		});
	},

	checkForValidForm: function(){
		if(this.$form.valid()){
			return true;
		}
	},

	startOver: function(){

		var $parents = this.$formStepParents,
				$firstParent = this.$formStepParents.eq(0),
				$formParent = this.$formParent,
				$stepsParent = this.$stepsParent;

				this.$resetButton.on("click", function(e){

					// hide all parents - show first
					$parents
						.removeClass(app.htmlClasses.visibleClass)
						.addClass(app.htmlClasses.hiddenClass)
						.eq(0).removeClass(app.htmlClasses.hiddenClass)
						.eq(0).addClass(app.htmlClasses.visibleClass);

						// remove edit state if present
						$formParent.removeClass(app.htmlClasses.editFormClass);

						// manage state - set to first item
						app.handleState(0);

						// reset stage for initial aria state
						app.setupAria();

						// send focus to first item
						setTimeout(function(){
							$firstParent.focus();
						},200);

				}); // click

	},

	handleState: function(step){

		this.$steps.eq(step).prevAll().removeAttr("disabled");
		this.$steps.eq(step).addClass(app.htmlClasses.activeClass);

		// restart scenario
		if(step === 0){
			this.$steps
				.removeClass(app.htmlClasses.activeClass)
				.attr("disabled","disabled");
			this.$steps.eq(0).addClass(app.htmlClasses.activeClass)
		}

	},

	editForm: function(){
		var $formParent = this.$formParent,
				$formStepParents = this.$formStepParents,
				$stepsParent = this.$stepsParent;

				this.$editButton.on("click",function(){
					$formParent.toggleClass(app.htmlClasses.editFormClass);
					$formStepParents.attr("aria-hidden",false);
					$formStepParents.eq(0).find("input").eq(0).focus();
					app.handleAriaExpanded();
				});
	},

	killEnterKey: function(){
		$(document).on("keypress", ":input:not(textarea,button)", function(event) {
			return event.keyCode != 13;
		});
	},

	handleStepClicks: function(){

		var $stepTriggers = this.$steps,
				$stepParents = this.$formStepParents;

				$stepTriggers.on("click", function(e){

					e.preventDefault();

					var btnClickedIndex = $(this).index();

						// kill active state for items after step trigger
						$stepTriggers.nextAll()
							.removeClass(app.htmlClasses.activeClass)
							.attr("disabled",true);

						// activate button clicked
						$(this)
							.addClass(app.htmlClasses.activeClass)
							.attr("disabled",false)

						// hide all step parents
						$stepParents
							.removeClass(app.htmlClasses.visibleClass)
							.addClass(app.htmlClasses.hiddenClass)
							.attr("aria-hidden",true);

						// show step that matches index of button
						$stepParents.eq(btnClickedIndex)
							.removeClass(app.htmlClasses.hiddenClass)
							.addClass(app.htmlClasses.visibleClass)
							.attr("aria-hidden",false)
							.focus();

				});

	}

};

app.init();

Output:

multi_step_form_wizard_jquery_validation_example

 


You might also like:

Recommended Post
Featured Post
How to Install Material Theme in Angular 17
How to Install Material Theme...

In this article, we'll install the material theme in angular 17. Material Theme brings a polished design and us...

Read More

Mar-29-2024

Laravel 9 Flash Message Example
Laravel 9 Flash Message Exampl...

In this article, we will see a laravel 9 flash message example. Here, we will learn how to create or implement flash mes...

Read More

Dec-27-2022

Mail: Laravel 11 Send Email using Queue
Mail: Laravel 11 Send Email us...

In this guide, we'll see how to send email using a queue in laravel 11. Here we'll see the concept of queue...

Read More

Apr-12-2024

500 Internal Server Error In Laravel 9 AJAX
500 Internal Server Error In L...

In this article, we will see 500 internal server errors in laravel 9 ajax. Also, we can see how to solve or fixed l...

Read More

Apr-17-2022