Wrapper Class In Lightning Component

Lightning Component:

<!--
Name: ContactList.cmp
--> 
<aura:component controller="ContactController">
    <!--Declare Event Handlers-->  
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <!--Declare Attributes-->
    <aura:attribute name="contactList" type="ContactController.ContactWrapper[]" />   
    <aura:attribute name="isSelectAll" type="boolean" default="false"/>
    
    <div class="slds-m-around_xx-large">
        <h1 class="slds-text-heading--medium">Contacts</h1>
        <br/>
        <!--Contact List Table-->
        <table class="slds-table slds-table--bordered slds-table--cell-buffer" role="grid">      
            <thead>  
                <tr class="slds-text-title--caps">
                    <th>           
                        <label class="slds-checkbox">
                            <ui:inputCheckbox value="{!v.isSelectAll}" change="{!c.handleSelectAllContacts}" aura:id="selectAll"/>
                            <span class="slds-checkbox--faux" />
                            <span class="slds-form-element__label"></span>
                        </label>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Name">Name</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Account">Account</div>
                    </th>
                    
                    <th scope="col">
                        <div class="slds-truncate" title="Phone">Phone</div>
                    </th>
                    
                    <th scope="col">
                        <div class="slds-truncate" title="Email">Email</div>
                    </th>
                </tr>
            </thead>
            <tbody>        
                <aura:iteration items="{!v.contactList}" var="con">
                    <tr>
                        <th>
                            <label class="slds-checkbox">
                                <ui:inputCheckbox aura:id="checkContact" value="{!con.isSelected}" text="{!con.Id}"/>
                                <span class="slds-checkbox--faux" />
                                <span class="slds-form-element__label"></span>
                            </label>
                        </th>
                        <th scope="row">
                            <div class="slds-truncate" title="{!con.Name}">{!con.Name}</div>
                        </th>
                        <td>
                            <div class="slds-truncate" title="{!con.Account}">{!con.Account}</div>
                        </td>
                        <th scope="row">
                            <div class="slds-truncate" title="{!con.Phone}">{!con.Phone}</div>
                        </th>
                        <td>
                            <div class="slds-truncate" title="{!con.Email}">{!con.Email}</div>
                        </td>
                    </tr>
                </aura:iteration>
            </tbody>
        </table>
        <div>
            <br/>
            <lightning:button label="Submit" class="slds-button_brand" onclick="{!c.handleSelectedContacts }"  />
        </div>
    </div>
</aura:component>

Lightning JS Controller:

({
    //get Contact List from apex controller
    doInit : function(component, event, helper) {
        var action = component.get("c.getContactList");
        action.setParams({
        });
        action.setCallback(this, function(result){
            var state = result.getState();
            if (component.isValid() && state === "SUCCESS"){
                component.set("v.contactList",result.getReturnValue());   
            }
        });
        $A.enqueueAction(action);
    },
    
    //Select all contacts
    handleSelectAllContacts: function(component, event, helper) {
        var getID = component.get("v.contactList");
        var checkvalue = component.find("selectAll").get("v.value");        
        var checkContact = component.find("checkContact"); 
        if(checkvalue == true){
            for(var i=0; i<checkContact.length; i++){
                checkContact[i].set("v.value",true);
            }
        }
        else{ 
            for(var i=0; i<checkContact.length; i++){
                checkContact[i].set("v.value",false);
            }
        }
    },
    
    //Process the selected contacts
    handleSelectedContacts: function(component, event, helper) {
        var contactList = component.get("v.contactList");
        var isSelectAll = component.get("v.isSelectAll");
        
        var selectedContacts = [];
        
        if(isSelectAll){
            selectedContacts = contactList;
        }
        else{
            var k = 0;
            for (var i=0; i<contactList.length; i++){
                var c = contactList[i];
                if(c.isSelected) {
                    selectedContacts[k] = c;
                    k++; 
                }     
            }
        }
        
        if(selectedContacts.length > 0){
            var contactRecords = JSON.stringify(selectedContacts);
            var action = component.get("c.processSelectedContacts");
            action.setParams({
                contactRecords : contactRecords
            });
            action.setCallback(this, function(result){
                var state = result.getState();
                if (component.isValid() && state === "SUCCESS"){
                    alert('Success in calling server side action');
                }
                else if(state == "ERROR"){
                    alert('Error in calling server side action');
                }
            });
            $A.enqueueAction(action);
        }
    }
})

Apex Controller:

public class ContactController {
    
    @AuraEnabled
    Public static List<ContactWrapper> getContactList(){
        List<ContactWrapper> contactList = new List<ContactWrapper>(); 
        //get all contact list
        List<Contact> conList = [SELECT Id, Name, Account.Name, Phone, Email FROM Contact LIMIT 10];
        for(Contact con : conList){
            ContactWrapper obj = new ContactWrapper();
            obj.ContactId = con.Id;
            obj.Name = con.Name;
            obj.Account = con.Account.Name;
            obj.Phone = con.Phone;
            obj.Email = con.Email;
            obj.isSelected = false; 
            contactList.add(obj);
        }
        return contactList;
    }
    
    @AuraEnabled
    Public static void processSelectedContacts(string contactRecords){
        system.debug('contactRecords-' + contactRecords);
        List<ContactWrapper> contactList = new  List<ContactWrapper>();
        if(!string.isBlank(contactRecords)){
            contactList = (List<ContactWrapper>)System.JSON.deserialize(contactRecords,List<ContactWrapper>.class);
            system.debug('contactList-' + contactList);
        }
    }
    
    public class ContactWrapper{
        @AuraEnabled
        public String ContactId {get;set;}
        @AuraEnabled
        public String Name {get;set;}
        @AuraEnabled
        public String Account {get;set;}
        @AuraEnabled
        public String Phone {get;set;}
        @AuraEnabled
        public String Email {get;set;}
        @AuraEnabled
        public boolean isSelected {get;set;}
    }
}

Dynamically Creating Lightning Components

Sample Component:

<!--
Name: Sample.cmp
--> 
<aura:component >    
    <div class="slds-m-around_xx-large">
        <label class="mdp-form-user-element__label" id="enteredName"></label><br/><br/>
        <lightning:button label="Add Your Name" variant="brand" onclick="{!c.handlePopup}"/>
    </div>
    {!v.body }
</aura:component>

Sample Component JS Controller:

({
    handlePopup : function(component, event,helper) {
        //Create Dynamic Component
        $A.createComponent('c:SampleModalPopup', {
            title: 'Please enter your name',
            
        }, function attachModal(modalCmp, status) {
            if (component.isValid() && status === 'SUCCESS') {
                var body = component.get("v.body");
                body.push(modalCmp);
                component.set("v.body", body);    
            }
        });
    }
})

ModalPopup Component:

<!--
    Name: ModalPopup.cmp
--> 
<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="title" type="String" />
    <div aura:id="modalDiv">
        <div role="dialog" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <div class="slds-modal__header">
                    <button class="slds-button slds-modal__close slds-button--icon-inverse" title="Close" onclick="{!c.handleCloseModal}">
                        X<span class="slds-assistive-text">Close</span>
                    </button>
                    <h1 class="slds-text-heading--medium">{!v.title}</h1>
                </div>
                
                <!--Modal Box Header-->
                <div class="slds-modal__content slds-p-around--medium">
                    <input type="text" placeholder="Please enter your name" id="userName" autofocus="autofocus" class="slds-input"/>
                </div>
                <!--Modal Box Button-->
                <div class="slds-modal__footer">
                    <lightning:button label="Submit" class="slds-button_brand" onclick="{!c.handleSubmit}"  />
                    <lightning:button label="Cancel" class="slds-button" onclick="{!c.handleCloseModal }"  />
                </div>
            </div>
        </div>
        <div class="slds-backdrop slds-backdrop--open"></div>            
    </div>
</aura:component>

ModalPopup JS Controller:

({
    doInit : function(component, event, helper) {
        console.log('Modal Popup Load');
    },
    
    handleSubmit : function(component, event, helper){
        var userName = document.getElementById("userName");
        var enteredName = document.getElementById("enteredName");
        enteredName.innerHTML = userName.value;
        
        var popupWindow = component.find('modalDiv').getElement();
        if(popupWindow){
            popupWindow.style.display = 'none';
        }
    },
    handleCloseModal : function(component, event, helper){
        var popupWindow = component.find('modalDiv').getElement();
        if(popupWindow){
            popupWindow.style.display = 'none';
        }
    }
})

Output:

Lightning Table With Multiple Checkbox Select Options

Here is an example of Lightning Contact List data table with multiple checkbox select option.

Apex Controller:

public class ContactAuraController {
    
    @AuraEnabled
    Public static List<Contact> getContactList(){
        //get all contact list
        List<Contact> conList = [SELECT Id, Name, Account.Name, Phone, Email FROM Contact LIMIT 10];
        return conList;
    }
}

Component:

<!--
Name: ContactList.cmp
--> 
<aura:component controller="ContactAuraController">
    <!--Declare Event Handlers-->  
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <!--Declare Attributes-->
    <aura:attribute name="contactList" type="list" />   
    <aura:attribute name="isSelectAll" type="boolean" default="false"/>
    
    <div class="slds-m-around_xx-large">
        <h1 class="slds-text-heading--medium">Contacts</h1>
        <br/>
        <!--Contact List Table-->
        <table class="slds-table slds-table--bordered slds-table--cell-buffer" role="grid">      
            <thead>  
                <tr class="slds-text-title--caps">
                    <th>           
                        <label class="slds-checkbox">
                            <ui:inputCheckbox value="{!v.isSelectAll}" change="{!c.handleSelectAllContact}" aura:id="selectAll"/>
                            <span class="slds-checkbox--faux" />
                            <span class="slds-form-element__label"></span>
                        </label>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Name">Name</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Account">Account</div>
                    </th>
                    
                    <th scope="col">
                        <div class="slds-truncate" title="Phone">Phone</div>
                    </th>
                    
                    <th scope="col">
                        <div class="slds-truncate" title="Email">Email</div>
                    </th>
                </tr>
            </thead>
            <tbody>        
                <aura:iteration items="{!v.contactList}" var="con">
                    <tr>
                        <th>
                            <label class="slds-checkbox">
                                <ui:inputCheckbox aura:id="checkContact" value="" text="{!con.Id}"/>
                                <span class="slds-checkbox--faux" />
                                <span class="slds-form-element__label"></span>
                            </label>
                        </th>
                        <th scope="row">
                            <div class="slds-truncate" title="{!con.Name}">{!con.Name}</div>
                        </th>
                        <td>
                            <div class="slds-truncate" title="{!con.Account.Name}">{!con.Account.Name}</div>
                        </td>
                        <th scope="row">
                            <div class="slds-truncate" title="{!con.Phone}">{!con.Phone}</div>
                        </th>
                        <td>
                            <div class="slds-truncate" title="{!con.Email}">{!con.Email}</div>
                        </td>
                    </tr>
                </aura:iteration>
            </tbody>
        </table>
        <div>
            <br/>
            <lightning:button label="Submit" class="slds-button_brand" onclick="{!c.handleSelectedContacts }"  />
        </div>
    </div>
</aura:component>

Component JS Controller:

({
    //get Contact List from apex controller
    doInit : function(component, event, helper) {
        var action = component.get("c.getContactList");
        action.setParams({
        });
        action.setCallback(this, function(result){
            var state = result.getState();
            if (component.isValid() && state === "SUCCESS"){
                component.set("v.contactList",result.getReturnValue());   
            }
        });
        $A.enqueueAction(action);
    },
    
    //Select all contacts
    handleSelectAllContact: function(component, event, helper) {
        var getID = component.get("v.contactList");
        var checkvalue = component.find("selectAll").get("v.value");        
        var checkContact = component.find("checkContact"); 
        if(checkvalue == true){
            for(var i=0; i<checkContact.length; i++){
                checkContact[i].set("v.value",true);
            }
        }
        else{ 
            for(var i=0; i<checkContact.length; i++){
                checkContact[i].set("v.value",false);
            }
        }
    },
    
    //Process the selected contacts
    handleSelectedContacts: function(component, event, helper) {
        var selectedContacts = [];
        var checkvalue = component.find("checkContact");
        
        if(!Array.isArray(checkvalue)){
            if (checkvalue.get("v.value") == true) {
                selectedContacts.push(checkvalue.get("v.text"));
            }
        }else{
            for (var i = 0; i < checkvalue.length; i++) {
                if (checkvalue[i].get("v.value") == true) {
                    selectedContacts.push(checkvalue[i].get("v.text"));
                }
            }
        }
        console.log('selectedContacts-' + selectedContacts);
    }
})

Output:

USA Standard Telephone Formatting in Lightning Experience

I had a requirement to automate a Phone number field to USA standard format. As of now in Lightning there is no such feature exists.

Here is an example:
Phone: 9831078379
USA Standard Format: (983) 107-8379

Component:

<aura:component>
    <div class="slds-m-around_xx-large">
        <lightning:input type="text" maxlength="10" onblur = "{!c.formatPhoneNumber}" aura:id="Phone" label="Phone" name="Phone"/>
    </div>
</aura:component>

JS Controller:

({
    formatPhoneNumber: function(component, helper, event) {
        var phoneNo = component.find("Phone");
        var phoneNumber = phoneNo.get('v.value');
        var s = (""+phoneNumber).replace(/\D/g, '');
        var m = s.match(/^(\d{3})(\d{3})(\d{4})$/);
        var formattedPhone = (!m) ? null : "(" + m[1] + ") " + m[2] + "-" + m[3];
        phoneNo.set('v.value',formattedPhone);
    }
})

Output:
USA-Standard-Phone-Format-in-Lightning-Experience

Bound and Unbound Expressions in Lightning Components

When we work with components, the first thing we do is declaring the attributes and initialize them. We use expressions for initializing our components. There are two types of expressions, bound and unbound that are used to perform data binding in Lightning Components.

Bound Expression: Bound Expression is represented as {!v.str}. Whenever the value of the string is changed, this expression will reflect the change and also affect the components where it is used, we can say the value change dynamically through this expression.

Unbound Expression: Unbound Expression is represented as {#v.str}. Whenever the value of the string is changed, this expression will not reflect the change, we can say the value remains static through this expression.

Here is an example of lightning component with Bound and Unbound Expressions:

Sample Component:

<aura:component>
    <aura:attribute name="str" type="string" default="Hello World!"/>
    <ui:outputText value="Enter a string value : "/>
    <ui:inputText value="{!v.str}"/>
    <br/>
    <ui:outputText value="Unboud Expression : "/>
    <ui:outputText value="{#v.str}"/>
    <br/>
    <ui:outputText value="Bound Expression : "/>
    <ui:outputText value="{!v.str}"/>
</aura:component>

Output:
bound-and-unbound-expressions

The value in bound expression variable changes on change of the input, but the value of unbound expression remains the same.