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
Laravel 9 orWhere Condition Example
Laravel 9 orWhere Condition Ex...

In this article, we will see the laravel 9 orWhere condition example. Where condition is joined together using the ...

Read More

Oct-13-2022

How To Remove Package From Laravel
How To Remove Package From Lar...

In this article, we will see how to remove the package from laravel. there are different ways to remove packages fr...

Read More

Oct-31-2022

Laravel 9 Multiple Authentication Using Middleware
Laravel 9 Multiple Authenticat...

In this article, we will see laravel 9 multiple authentications using middleware. Using middleware we authenticate the u...

Read More

Apr-13-2022

How To Add Foreign Key In Laravel 10 Migration
How To Add Foreign Key In Lara...

In this article, we will see how to add a foreign key in laravel 10 migration. Here, we will learn about laravel 10...

Read More

May-05-2023