Usage of lightning:tab

A lightning:tabset displays a tabbed container with multiple content areas, only one of which is visible at a time. Tabs are displayed horizontally inline with content shown below it. A tabset can hold multiple lightning:tab components as part of its body. The first tab is activated by default, but you can change the default tab by setting the selectedTabId attribute on the target tab.

Use the variant attribute to change the appearance of a tabset. The variant attribute can be set to default, scoped, or vertical. The default variant underlines the active tab. The scoped tabset styling displays a closed container with a defined border around the active tab. The vertical tabset displays a scoped tabset with the tabs displayed vertically instead of horizontally.

 

 

public class TabController {
    @AuraEnabled
    public static List<Account> getAccounts(){
        return [Select Id ,Name from Account Limit 10] ;  
    }
    @AuraEnabled
    public static List<Contact> getContacts(){
        return [Select Id ,Name from Contact Limit 10] ;    
    }
    @AuraEnabled
    public static List<Campaign> getCam(){
        return [Select Id ,Name from Campaign Limit 10] ; 
    }
    @AuraEnabled
    public static List<Case> getCases(){
        return [Select Id ,casenumber from Case Limit 10] ; 
    }
    
}

 

 

 

<aura:component controller="TabController">
    
    
    <aura:attribute name="obj" type="SObject[]" default="" />
    
     
    
    <lightning:tabset variant="scoped">
        <lightning:tab title="Account Details " id="accounts" onactive="{! c.handleActive }">
            <aura:set attribute="label" >
                Account
                <lightning:icon iconName="standard:account" />
            </aura:set>
            <aura:set attribute="body" >
                <aura:iteration items="{!v.obj}" var="item">
                    <ul>
                        <li>    {!item.Name}-- {!item.Id}   </li> 
                    </ul>
                </aura:iteration>
            </aura:set>
        </lightning:tab>
        <lightning:tab title="Contact Details " id="contacts" onactive="{! c.handleActive }">
            <aura:set attribute="label">
                Contact
                <lightning:icon iconName="standard:contact" />
            </aura:set>
            <aura:set attribute="body" >
                <aura:iteration items="{!v.obj}" var="item">
                    <ul>
                        <li>    {!item.Name}-- {!item.Id}   </li> 
                    </ul>
                </aura:iteration>
            </aura:set>
        </lightning:tab>
        <lightning:tab title="Campaign Details " id="campaign" onactive="{! c.handleActive }">
            <aura:set attribute="label">
                Campaign
                <lightning:icon iconName="standard:campaign" />
            </aura:set>
            <aura:set attribute="body" >
                <aura:iteration items="{!v.obj}" var="item">
                    <ul>
                        <li>    {!item.Name}-- {!item.Id}   </li> 
                    </ul>
                </aura:iteration>
            </aura:set>
        </lightning:tab>
        <lightning:tab title="Case Details " id="case" onactive="{! c.handleActive }">
            <aura:set attribute="label">
                Case
                <lightning:icon iconName="standard:case" />
            </aura:set>
            <aura:set attribute="body" >
                <aura:iteration items="{!v.obj}" var="item">
                    <ul>
                        <li>    {!item.casenumber}-- {!item.Id}   </li> 
                    </ul>
                </aura:iteration>
            </aura:set>
        </lightning:tab>
    </lightning:tabset>
</aura:component>

 

({
    handleActive: function (cmp, event, helper) {
        helper.loadData(cmp, event);
    },
    
})

 

 

({
    loadData: function (cmp, event) {
        var tab = event.getSource();
        switch (tab.get('v.id')) {
            case 'accounts' :
                this.loadContacts(cmp ,tab.get('v.id'));
                break;
            case 'contacts' :
                this.loadContacts(cmp ,tab.get('v.id'));
                break;
            case 'case' :
                this.loadContacts(cmp ,tab.get('v.id'));
                break;
            case 'campaign' :
                this.loadContacts(cmp ,tab.get('v.id'));
                break;
        }
    },
    loadContacts : function(cmp ,target) {
        var action ;
        console.log(target);
        if(target==='accounts'){
            console.log(target);
            action = cmp.get("c.getAccounts");
        }
        if(target==='contacts'){
            action = cmp.get("c.getContacts"); 
        }
        if(target==='case'){
            action = cmp.get("c.getCases"); 
        }
        if(target==='campaign'){
            action = cmp.get("c.getCam");
        }
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                console.log('response');
                console.log(response.getReturnValue());
                cmp.set("v.obj", response.getReturnValue());
                
            }
        });
        $A.enqueueAction(action);
    },
    
})

 

lightning:tree metatext example

A lightning:tree component displays the visualization of a structural hierarchy, such as a sitemap for a website or a role hierarchy in an organization. metatext one of the attributes which you can pass it to the array of items .metata attribute is used to provide users with supplemental information and aid with identification or disambiguation. For example, if you want to provide the contact details in the Items that are displaying as shown in the below image.

Apex Class 

public class TreeController {
    @AuraEnabled
    public static String getTreeData(){
        List<Account> accs = [Select Id , Name,Rating,Type,(Select Id , Name,FirstName ,LastName,Email from Contacts) from Account];
        Map<Id , Contact> opps =new Map<Id , Contact>( [Select Id , Name,(Select Id ,Name,Amount,StageName From Opportunities) from Contact]);
        
        List<AccountWrapper> aooo = new List<AccountWrapper>();
        for(Account a : accs){
            AccountWrapper aWraper = new AccountWrapper() ; 
            aWraper.name =a.Id ;
            aWraper.label =a.Name ;
            aWraper.metatext = a.Name+'-'+a.Type+'-'+a.Rating ;
            aWraper.expanded =false ;
            List<Items> co = new List<Items>();
            for(Contact c : a.Contacts){
                Items conWrapp = new Items();
                conWrapp.name =c.Id ;
                conWrapp.metatext =c.FirstName+'-'+c.LastName+'-'+c.Email;
                conWrapp.label =c.Name ;
                conWrapp.expanded =false ;
                
                List<Items> wrapperOooo = new List<Items>();
                for(Opportunity o : opps.get(c.Id).Opportunities){
                    Items ooo = new Items(); 
                    ooo.name = o.Id ;
                    ooo.label = o.Name ;
                    ooo.metatext =o.Name+'-'+o.Amount+'-'+o.StageName;
                    ooo.expanded = false ;
                    wrapperOooo.add(ooo);
                }
                
                conWrapp.items =wrapperOooo ;
                co.add(conWrapp);
            }
            aWraper.items = co;
            aooo.add(aWraper);
            
        }
        return JSON.serializePretty(aooo) ;
    } 
    public Class AccountWrapper{
        @AuraEnabled
        public String name {get;set;}
        @AuraEnabled
        public String label {get;set;}
        @AuraEnabled
        public String metatext {get;set;}
        @AuraEnabled
        public Boolean expanded {get;set;}
        @AuraEnabled
        public List<Items> items {get;set;}
        
    }
    public Class Items{
        @AuraEnabled
        public String name {get;set;}
        @AuraEnabled
        public String label {get;set;}
        @AuraEnabled
        public String metatext {get;set;}
        @AuraEnabled
        public Boolean expanded {get;set;}
        @AuraEnabled
        public List<Items> items {get;set;}
    }
    
}

Lightning Component 

<aura:component controller="TreeController">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:attribute name="items" type="Object"/>
    <lightning:tree items="{! v.items }" header="Account - Contact - Opportunity" onselect="{!c.handleSelect}"/>
</aura:component>

 

({
    doInit: function (cmp, event, helper) {
        var action = cmp.get("c.getTreeData");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.set('v.items', JSON.parse(response.getReturnValue()));
            }
            
        });
        $A.enqueueAction(action);
    },
    handleSelect: function (cmp, event, helper) {
        //return name of selected tree item
        var id = event.getParam('name');
        var urlEvent = $A.get("e.force:navigateToURL");
        urlEvent.setParams({
            "url": "/"+id
        });
        urlEvent.fire();
    }
    
})

 

Navigate to Component Using lightning:navigation

in this example, we will see how to navigate from the one lightning component another component using lightning:navigation. Use lightning:navigation component to navigate to a given pageReference or to generate a URL from a pageReference.  PageReference is a reference to a page, providing a well-defined structure that describes the page type and its corresponding values. You should use the PageReference definitions instead of attempting to parse the URL directly. The following PageReference properties are supported.

type:- The API name of the PageDefinition like component or standard page etc.

attributes is an object of values for each attribute specified by the PageDefinition.

state This property defines the parameter of page URL to be generated.

The below is the simple component that we will be invoking from another component by using navigation API.

Target.cmp

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,lightning:isUrlAddressable" access="global" >
    <aura:handler name="init" value="{!this}" action="{!c.init}" />

    <aura:attribute name="firstName" type="String" />
    <aura:attribute name="lastName" type="String" />
    <div>
        Full Name : {!v.firstName} + {!v.lastName}
    </div>
</aura:component>
({
    init: function(cmp, event, helper) {
        var pageReference = cmp.get("v.pageReference");
        cmp.set("v.firstName", pageReference.state.firstName);
        cmp.set("v.lastName", pageReference.state.lastName);
    }
})

In the init handler we are getting the page reference from the navigation API and setting the attributes.

Source.cmp

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <lightning:navigation aura:id="navService"/>
    <aura:attribute name="pageReference" type="Object"/>
    <aura:attribute name="url" type="String"/>
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    <lightning:button label="Open Lightning Component" onclick="{!c.handleClick}"/>
    
</aura:component>

Controller.js

({
    init : function(cmp, event, helper) {
        var navService = cmp.find("navService");
        var pageReference = {
            
            "type": "standard__component",
            "attributes": {
                "componentName": "c__Target"    
            },    
            "state": {
                "firstName": "Test"  ,
                "lastName": "user"    
            }
        };
        cmp.set("v.pageReference", pageReference);
        var defaultUrl = "#";
        navService.generateUrl(pageReference)
        .then($A.getCallback(function(url) {
            cmp.set("v.url", url ? url : defaultUrl);
        }), $A.getCallback(function(error) {
            cmp.set("v.url", defaultUrl);
        }));
    },
    handleClick: function(cmp, event, helper) {
        var navService = cmp.find("navService");
        // Uses the pageReference definition in the init handler
        var pageReference = cmp.get("v.pageReference");
        event.preventDefault();
        navService.navigate(pageReference);
    }
})

In the client-side controller, set the pageReference attribute for the lightning component and set the state and attributes. Set the URL on your link using the generateUrl() method on the init handler.

handleClick method on the button click will navigate to the Target component.

 

 

Usage Of force:recordView

A force:recordView component represents a read-only view of a record. By default, the record view uses the full layout to display all fields of the record. The type attribute does not support any other value so you don’t need to specify it. In this example, we will see how to use the force:recordview along with datatable. we will show the row details on click of the row action by using force:recordview

Apex Class 

public class GetAllAccounts {
    @AuraEnabled
    public static List<Account> getAllAccounts(){
        return [Select Id,Name ,AnnualRevenue,Description,NumberOfEmployees,Industry,Rating,Phone from Account] ; 
    }
}

 

Lightning Component 

Here is the simple lightning component

<aura:component controller="GetAllAccounts"  implements="flexipage:availableForAllPageTypes,force:appHostable,flexipage:availableForRecordHome,force:hasRecordId,force:hasSObjectName">
    <lightning:overlayLibrary aura:id="overlayLib"/>
    
    <aura:attribute name="data" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    <aura:attribute name="errors" type="Object" default="[]"/>
    
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    <div style="height: 300px">
        <lightning:datatable aura:id="dtTable"
                             columns="{! v.columns }"
                             data="{! v.data }"
                             keyField="Id"
                             errors="{! v.errors }"
                             onrowaction="{! c.handleRowAction }"
                             
                             />
    </div>
</aura:component>

controller.js

({
    init: function (cmp, event, helper) {
        
        var actions = [
            { label: 'View', name: 'View' }
        ];
        
        
        cmp.set('v.columns', [
            {label: 'Id', fieldName: 'Id', type: 'text' },
            {label: 'Name', fieldName: 'Name', type: 'text' },
            {label: 'Number Of Employees', fieldName: 'NumberOfEmployees', type: 'number'},
            {label: 'Industry', fieldName: 'Industry', type: 'text' },
            {label: 'Phone', fieldName: 'Phone', type: 'phone'  }  ,
            { type: 'action', typeAttributes: { rowActions: actions } }
            
        ]);
        helper.fetchData(cmp,event, helper);
    },
    handleRowAction: function (cmp, event, helper) {
        var row = event.getParam('row');
        console.log('row'+row.Id);
        var modalBody;
        $A.createComponent("force:recordView", {"recordId":row.Id},
                           function(content, status) {
                               if (status === "SUCCESS") {
                                   modalBody = content;
                                   cmp.find('overlayLib').showCustomModal({
                                       body: modalBody, 
                                       showCloseButton: true,
                                       closeCallback: function() {
                                       }
                                   })
                               }                               
                           });
        
    },
})

helper.js

({
    fetchData: function (cmp,event,helper) {
        var action = cmp.get("c.getAllAccounts");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var data = response.getReturnValue();
                cmp.set('v.data',data);
            }
            // error handling when state is "INCOMPLETE" or "ERROR"
        });
        $A.enqueueAction(action);
    }
})

Key highlights of the code 

The following code is used to show the row-level action on datatable

            { type: 'action', typeAttributes: { rowActions: actions } }

Below controller handler is used to handler the row level actions.

handleRowAction: function (cmp, event, helper) {
}

the following controller action logic is used to create a force:recordview and passes the record id to the record view based on the row action.

 $A.createComponent("force:recordView", {"recordId":row.Id},
                           function(content, status) {
                               if (status === "SUCCESS") {
                                   modalBody = content;
                                   cmp.find('overlayLib').showCustomModal({
                                       body: modalBody, 
                                       showCloseButton: true,
                                       closeCallback: function() {
                                           //    alert('You closed the alert!');
                                       }
                                   })
                               }                               
                           });