Lightning Wizard Component with jQuery and Bootstrap

Posted on Updated on

Hi All,

In this post I am sharing with you a Lightning Wizard Component built with Bootstrap and jQuery.
It is a multi step form wizard with Progress Bar and jQuery Validations.

IMG-20150623-WA0002 IMG-20150623-WA0005 IMG-20150623-WA0004

Requirements :
1) Download latest version of Bootstrap and jQuery.
2) “bklightning” namespace to “YourNamespace”.

Here is full code :

WizardDemoComponent.cmp
<aura:component controller="bklightning.CreateContactController" implements="force:appHostable">
    <ltng:require styles="/resource/wizarddemo/wizarddemo/bootstrap.min.css,/resource/wizarddemo/wizarddemo/style.css"
                  scripts="/resource/wizarddemo/wizarddemo/jquery.min.js,
                           /resource/wizarddemo/wizarddemo/jquery-ui.min.js,
                           /resource/wizarddemo/wizarddemo/jquery.validate.js,
                           /resource/wizarddemo/wizarddemo/bootstrap.min.js"
                  afterScriptsLoaded="{!c.afterLoaded}"/>
    
    <aura:attribute name="newContact" type="bklightning__ContactDetail__c"
                                        default="{ 'sobjectType': 'bklightning__ContactDetail__c'}"/>
    
    <div class="container">
    <br/><br/>
	<form class="form-horizontal form" id="form">
		<div class="col-md-8 col-md-offset-2">   	
			<div class="progress">
			  <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"></div>
			</div>
		
			<div class="box row-fluid">	
				<br/>
				<div class="step">
					<div class="form-group">
						<label for="fname" class="col-sm-2 control-label">First Name</label>
						<div class="col-sm-10">
						  <input type="text" name="fname" value="{!v.newContact.bklightning__Firstname__c}" class="form-control" id="fname" placeholder="First Name"/>
						</div>
					</div>
					<div class="form-group">
						<label for="lname" class="col-sm-2 control-label">Last Name</label>
						<div class="col-sm-10">
						  <input type="text" name="lname" value="{!v.newContact.bklightning__Lastname__c}"  class="form-control" id="lname" placeholder="Last Name"/>
						</div>
					</div>
					<div class="form-group">
						<label for="email" class="col-sm-2 control-label">Email</label>
						<div class="col-sm-10">
						  <input type="text" name="email" value="{!v.newContact.bklightning__Email__c}" class="form-control" id="email" placeholder="email"/>
						</div>
					</div>			  
					  
				</div>
				<div class="step">
					<div class="form-group">
						<label for="phone" class="col-sm-2 control-label">Phone</label>
						<div class="col-sm-10">
						  <input type="text" name="phone" value="{!v.newContact.bklightning__Phone__c}" class="form-control" id="phone" placeholder="Phone"/>
						</div>
					</div>
					<div class="form-group">
						<label for="address" class="col-sm-2 control-label">Address</label>
						<div class="col-sm-10">
						  <textarea name="address" class="form-control" id="address" cols="10" rows="5" >{!v.newContact.bklightning__Address__c}</textarea>
						</div>
					</div>			  
					  
				</div>
				<div class="step display">
					<div class="form-group">
						<label for="company" class="col-sm-2 control-label">Company</label>
						<div class="col-sm-10">
							<input type="text" name="company" value="{!v.newContact.bklightning__Company__c}" class="form-control" id="company" placeholder="Company"/>
						</div>
					</div>
					<div class="form-group">
						<label for="numberofemp" class="col-sm-2 control-label">Number of Employees</label>
						<div class="col-sm-10">
							<input type="text" name="numberofemp" value="{!v.newContact.bklightning__NumberOfEmployee__c}" class="form-control" id="numberofemp" placeholder="Number of Employees"/>
						</div>
					</div>			  
					<div class="form-group">
						<label for="website" class="col-sm-2 control-label">Website</label>
						<div class="col-sm-10">
							<input type="text" name="website" value="{!v.newContact.bklightning__Website__c}" class="form-control" id="website" placeholder="Website"/>
						</div>
					</div>			  
				</div>
			
				<div class="row">
					<div class="showMsg" style="display:none;color:red;text-align:center;">
						<b>Your Information Saved Successfully</b><br/>
					</div>
				</div>
            
				<div class="row">
					<div class="col-sm-12">
						<div class="pull-right">
							<button type="button" class="action btn-sky text-capitalize back btn">Back</button>
							<button type="button" class="action btn-sky text-capitalize next btn">Next</button>
							<button type="button" onclick="{!c.saveContact}" class="action btn-hot text-capitalize submit btn">Submit</button>
						</div>
					</div>
				</div>			

			</div>
		
			</div> 
		</form> 
	</div>
</aura:component>

In WizardDemoComponent.cmp you can see I have used Latest Bootstrap and jQuery Library.
When all scripts loaded I am calling afterLoaded() function of WizardDemoComponentController.js.

WizardDemoComponentController.js
({
	afterLoaded : function(component, event, helper) {
        var current = 1;
        
        widget = jQuery(".step");
		btnnext = jQuery(".next");
		btnback = jQuery(".back"); 
		btnsubmit = jQuery(".submit");
        
        widget.not(':eq(0)').hide();
		
		helper.hideButtons(component,widget,current);
        helper.setProgress(component,widget,current);
        
        //Next Button Action
        btnnext.click(function(){
			if(current < widget.length){
				// Check validation
				if(jQuery(".form").valid()){
					widget.show();
					widget.not(':eq('+(current++)+')').hide();
					helper.setProgress(component,widget,current);
				}
			}
			helper.hideButtons(component,widget,current);
		})
        
        //Back Button Action
        btnback.click(function(){
			if(current > 1){
				current = current - 2;
				if(current < widget.length){
					widget.show();
					widget.not(':eq('+(current++)+')').hide();
					helper.setProgress(component,widget,current);
				}
			}
			helper.hideButtons(component,widget,current);
		})
		
		jQuery('.form').validate({ // initialize plugin
			ignore:":not(:visible)",			
			rules: {
				fname     : "required",
				lname     : "required",
				email    : {required : true, email:true},
				phone  : {required : true, number:true},
				address : "required",
				company : "required",
				website : {required : true, url:true},
				numberofemp : {required : true, number:true},
			},
	    });
        
	},
    
    saveContact : function(component, event, helper) {
        component.set("v.newContact.bklightning__Firstname__c",jQuery("#fname").val());
        component.set("v.newContact.bklightning__Lastname__c",jQuery("#lname").val());
        component.set("v.newContact.bklightning__Email__c",jQuery("#email").val());
        component.set("v.newContact.bklightning__Phone__c",jQuery("#phone").val());
        component.set("v.newContact.bklightning__Address__c",jQuery("textarea#address").val());
        component.set("v.newContact.bklightning__Company__c",jQuery("#company").val());
        component.set("v.newContact.bklightning__NumberOfEmployee__c",jQuery("#numberofemp").val());
        component.set("v.newContact.bklightning__Website__c",jQuery("#website").val());
        
        var newContact = component.get("v.newContact");
        
		helper.upsertContact(component, newContact); 	
        
        jQuery('.showMsg').show();
        jQuery('.form')[0].reset();
    }
    
})

In afterLoaded method of WizardDemoComponentController.js I am defining validations and click events.

WizardDemoComponentHelper.js
({
	setProgress : function(component,widget,currstep) {
		var percent = parseFloat(100 / widget.length) * currstep;
		percent = percent.toFixed();
		jQuery(".progress-bar").css("width",percent+"%").html(percent+"%");
	},
    
    hideButtons : function(component, widget,current) {
		var limit = parseInt(widget.length); 

		jQuery(".action").hide();

		if(current < limit) jQuery(".next").show();
		if(current > 1) jQuery(".back").show();
		if (current == limit) { 
			// Show entered values
			jQuery(".display label:not(.control-label)").each(function(){
				console.log(jQuery(this).find("label:not(.control-label)").html(jQuery("#"+jQuery(this).data("id")).val()));	
			});
			jQuery(".next").hide(); 
			jQuery(".submit").show();
		}	
	},
    
    upsertContact : function(component, newContact) {
        var action = component.get("c.createContact");
        action.setParams({
          "con": newContact
        });
        action.setCallback(this, function(a) {
        });
        $A.enqueueAction(action);
    }
})

In WizardDemoComponentHelper.js setProgress() and hideButtons() methods are used to set progress-bar and to hide buttons as wizard progresses.

So that’s it,Simple.

33 thoughts on “Lightning Wizard Component with jQuery and Bootstrap

    Chris Nuvoli said:
    June 30, 2015 at 4:31 pm

    Could you adapt this to Laravel 5.1?

    Liked by 1 person

      balkishankachawa responded:
      July 1, 2015 at 2:44 am

      Sorry Chris I do not have knowledge about this Framework but I can help you to implement this.

      Like

        Dhamodhar said:
        August 8, 2017 at 6:52 am

        I am getting n[0].hasOwnProperty jquery UI error. can you please help me out.

        Like

    Shreya K said:
    November 3, 2015 at 5:32 pm

    Thanks for your tutorial! It’s been very helpful in getting set up. I’m having trouble saving the Contact once the fields are populated. What does the bklightning.CreateContactController look like? I’m not able to get this line to work in the Helper js file : var action = component.get(“c.createContact”);

    Like

      balkishankachawa responded:
      November 3, 2015 at 5:45 pm

      Thanks Shreya for your valuable comment. In bklightning.CreateContactController bklightning is namespace and CreateContactController is the name of Apex Class. If you did not register for namespace you can remove bklightning and just use CreateContactController. Hope this will be helpful đŸ™‚

      Like

      Gabbar said:
      March 13, 2017 at 5:38 am

      Shreya can you please send Apex controller to hyd.maverick@gmail.com

      Like

    balkishankachawa responded:
    November 3, 2015 at 5:45 pm

    Thanks Shreya for your valuable comment. In bklightning.CreateContactController bklightning is namespace and CreateContactController is the name of Apex Class. If you did not register for namespace you can remove bklightning and just use CreateContactController. Hope this will be helpful đŸ™‚

    Like

      Shreya K said:
      November 3, 2015 at 6:50 pm

      I did remove the namespace but where is CreateContactController apex class? What does it look like for you?

      Like

        balkishankachawa responded:
        November 3, 2015 at 6:55 pm

        Actually i did not post this Apex Controller you can write this controller or give me your email id i will send you.

        Like

      Jayahsree said:
      September 14, 2016 at 9:31 am

      Hi Balkishankachawa,

      Please provide me the apex controller that is CreateContactController

      Like

    balkishankachawa responded:
    November 3, 2015 at 7:25 pm

    I sent you Apex Controller code please check your inbox.

    Like

      Shreya K said:
      November 3, 2015 at 7:27 pm

      Thanks so much! Got it.

      Like

      lmahesh26 said:
      February 3, 2016 at 9:34 am

      Great and very informative article! As with Shreya, can you send me the apex controller code?
      Thanks!

      Like

        balkishankachawa responded:
        February 3, 2016 at 9:43 am

        Thanks!! check your inbox I sent you apex code.

        Like

        lmahesh26 said:
        February 3, 2016 at 9:45 am

        Thanks for providing the apex class so fast!

        Great job with the articles!

        Like

        balkishankachawa responded:
        February 3, 2016 at 9:55 am

        Thanks!! Keep visiting đŸ™‚ Keep giving feedback

        Like

    freelanceworks2014 said:
    March 25, 2016 at 3:12 pm

    can you send me the Apex Controller code please !

    Like

    Amul Baranwal said:
    October 17, 2016 at 10:49 am

    can you send me the Apex Controller code please?

    Like

    Arshu said:
    January 31, 2017 at 4:59 pm

    Wonderful article on wizard creation. Could you provide me the apex controller code?

    Like

    riaz said:
    February 10, 2017 at 10:36 am

    please send the apex code

    Like

    Moustapha said:
    February 17, 2017 at 2:18 pm

    Great article ! can you send me please the apex controller code?
    Thanks!

    Like

    Bhargav said:
    February 21, 2017 at 4:57 am

    Can you please send me the apex controller?

    Like

    Gabbar said:
    March 11, 2017 at 4:13 am

    Can you please send me the Apex Controller code. That would be very helpful.

    Like

    Gabbar said:
    March 13, 2017 at 5:16 am

    Can you please send me the apex controller

    Like

    Teena said:
    March 13, 2017 at 7:13 am

    Can you please explain bklightning__Firstname__c is that a custom field in custom object bklightning. Can you also please send me the Apex controller. I am very new to lightning i have pasted all three codes into the component, controller and style but its not working as shown in snapshots

    Like

      balkishankachawa responded:
      March 29, 2017 at 3:12 pm

      Yes this is custom field. Please give me your email id.

      Like

    Rusty said:
    June 28, 2017 at 2:53 am

    Hey there can I bug you for the controller as well?

    Like

      balkishankachawa responded:
      June 28, 2017 at 6:59 am

      You can find Controller below:

      public class CreateContactController{

      @AuraEnabled
      public static void createContact(ContactDetail__c con) {
      insert con;
      }

      }

      Like

        Raja said:
        September 6, 2017 at 10:45 am

        Hi can you send the js and required scripts to me.This is my mail raja.nr1021@gmail.com.Your blog is nice i want to use your plugin for my project to complete.Thanks

        Like

    Srikanth said:
    October 7, 2017 at 6:39 am

    Can you please send the static resources files , where i have tried a lot but couldn’t get it , urgent !!!!!!!!!!!!!!!!!!

    Like

    amit said:
    November 27, 2017 at 10:20 am

    send the static resources files .my id amitsri2509@gmail.com

    Like

Leave a comment