Salesforce Lightning TreeGrid

A lightning:treeGrid component displays hierarchical data in a table. Its appearance resembles lightning:datatable, with the exception that each row can be expanded to reveal a nested group of items. Rows that contain nested data display a chevron icon to denote that they can be expanded or collapsed. Each column can be displayed based on the data type. Here is an example of lightning:datatable.

Note: This component requires API version 42.0 and later.

Apex Controller:

public class SampleAuraController {
    
    @AuraEnabled
    public static List <Account> getAccountList() {
        List<Account> accList = new List<Account>();
        accList = [SELECT Id, Name, NumberOfEmployees, Phone,
                   (SELECT FirstName, LastName, Email FROM Contacts)
                   FROM Account LIMIT 10];
        return accList;
    }
}

Lightning Component:

<!--Sample.cmp--> 
<aura:component controller="SampleAuraController" implements="flexipage:availableForAllPageTypes" access="global">
    <aura:attribute type="Account[]" name="acctList"/>
    <aura:attribute name="gridColumns" type="List" />
    <aura:attribute name="gridData" type="Object" />
    <aura:attribute name="gridExpandedRows" type="Object" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <div class="slds-m-around_xx-large">
        <lightning:treeGrid aura:id="accTree" columns="{!v.gridColumns}" data="{!v.gridData}" keyField="Id"/>
    </div>
</aura:component>

Lightning Component JS Controller:

({
    doInit : function(component, event, helper) {
        var columns = [
            {
                type: 'text',
                fieldName: 'Name',
                label: 'Account Name'
            },
            {
                type: 'number',
                fieldName: 'NumberOfEmployees',
                label: 'Employees'
            },
            {
                type: 'phone',
                fieldName: 'Phone',
                label: 'Phone Number'
            },
            {
                type: 'text',
                fieldName: 'FirstName',
                label: 'First Name'
            },
            {
                type: 'text',
                fieldName: 'LastName',
                label: 'Last Name'
            },
            {
                type: 'email',
                fieldName: 'Email',
                label: 'Email'
            }
        ];
        component.set('v.gridColumns', columns);
        var action = component.get("c.getAccountList");
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS" ) {
                var resultData = response.getReturnValue();
                for (var i=0; i<resultData.length; i++ ) {
                    resultData[i]._children = resultData[i]['Contacts'];
                    delete resultData[i].Contacts; 
                }
                component.set('v.gridData', resultData);
            }
        });
        $A.enqueueAction(action);
    }
})

Output:

Reference: lightning:treeGrid

Get Record Id From lightning:recordeditform in onsuccess Event

Sometimes we can have a requirement to get record Id in onsuccess event of lightning:recordeditform. In below example, I’m creating “Lead” object record using lightning:recordeditform and after successfully saving the record, getting the record Id in onsuccess event.

Lightning Component:

<!--Sample.cmp--> 
<aura:component implements="flexipage:availableForAllPageTypes,force:appHostable">
    
    <!--Component--> 
    <div class="slds-m-around--xx-large">
        <lightning:card title="Lead" iconName="standard:lead" class="slds-p-around_medium">
            <lightning:recordEditForm aura:id="leadCreateForm" objectApiName="Lead" onsuccess="{!c.handleOnSuccess}">
                <lightning:messages />
                
                <div class="slds-grid">
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="FirstName"></lightning:inputField>
                    </div>
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="LastName"></lightning:inputField>
                    </div>
                </div>
                
                <div class="slds-grid">
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="Email"></lightning:inputField>
                    </div>
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="Phone"></lightning:inputField>
                    </div>
                </div>
                
                <div class="slds-grid">
                    <div class="slds-col slds-size_1-of-2 slds-p-around_medium">
                        <lightning:inputField fieldName="Company"></lightning:inputField>
                    </div>
                </div>
                
                <lightning:button type="submit" label="Save" variant="brand"/>
            </lightning:recordEditForm>
        </lightning:card>
    </div>
</aura:component>

Lightning JS Controller:

({
    handleOnSuccess : function(component, event, helper) {
        var params = event.getParams(); //get event params
        var recordId = params.response.id; //get record id
        console.log('Record Id - ' + recordId); 
    }
})

Documentation in Salesforce Lightning Component Bundle

Component documentation helps others understand and use your components. Here is a sample example of Lightning Component Documentation.

Sample Component:

<!--Sample.cmp--> 
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
    <strong>Sample Component</strong>
</aura:component>

To create documentation of above component, click DOCUMENTATION in the component sidebar of the Developer Console. Hereaura:description is to show the description of the component and aura:example is to show look and feel of the component.

<aura:documentation>
    <aura:description>
        <p>An <code>c:Sample</code> component represents an element that executes an action defined by a controller.</p>
    </aura:description>
    <aura:example name="Sample" ref="c:Sample" label="Using the c:Sample Component">
        <p>This example shows a simple setup of <code>Sample</code>.</p>
    </aura:example>
</aura:documentation>

The documentation you create will be available at https://.lightning.force.com/auradocs/reference.app, where is the name of your custom Salesforce domain and in the Component Library at https://.lightning.force.com/componentReference/suite.app where is the name of your custom Salesforce domain.

Google Charts in Visualforce Page

Salesforce has built in component for charts in visualforce page, but the limitation is some types of charts are not available. In such cases, we can use Google Chart for different types of charts. Here is an example of Google Chart in visualforce page.

  • You can find the list of all Google charts at Google Chart Gallery.
  • Find the right chart as per your requirement and go through the documentation for the data requirements of the chart.
  • You can download the Google Chart Javascript and upload it as a static resource, or you can direct call the Google Chart Javascript url in visualforce page.
  • Every Google Chart requires data in specific format, create the right forma data in apex controller, before sending it to visualforce page Google Chart.

Example: In below example I’m showing number of Accounts group by Country in a 3D Pie Chart.

Apex Class:

global with sharing class AccountChartController {
    
    @RemoteAction
    global static List<AggregateResult> getAccountData(){
        List<AggregateResult> accGroupList = [Select BillingCountry Country, Count(Id) NumberOfAccounts
                                              From Account Where BillingCountry != null
                                              Group By BillingCountry];
        return accGroupList;
    }
}

Visualforce Page:

<apex:page controller="AccountChartController">
    <!--Google Chart Javascript Resource-->
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"/>
    
    <!--Javascript Remote Function To Call Apex Controller Method-->
        <script type="text/javascript">
            //Load google chart
            google.charts.load('current', {packages: ['corechart']});
    google.charts.setOnLoadCallback(drawChart);
    
    var accData; //Variable to store data
    //Call remote action method
    AccountChartController.getAccountData(function(result, event){
        accData  = result; //get data from apex controller
    },{escape:true});
    
    //Draw google chart
    function drawChart() {
        //Create the data table.
        var data = new google.visualization.DataTable();
        //Add datatable columns
        data.addColumn('string', 'Country');
        data.addColumn('number', 'Number of Accounts');
        
        //Add datatable rows
        for(i = 0; i< accData.length; i++){
            data.addRow([accData[i].Country, accData[i].NumberOfAccounts]);
        }
        
        //Set chart options
        var options = {
            'title':'Accounts Group by Country',
            is3D: true,};
        
        //Instantiate and draw the chart.
        var chart = new google.visualization.PieChart(document.getElementById('myPieChart'));
        chart.draw(data, options);
    }
    </script>
    
    <!--Identify where the chart should be drawn-->
    <div id="myPieChart" style="width: 900px; height: 700px;"/>
</apex:page>

Output:

Disable Lightning Button After Click

In below example I’m creating Lead records from a Lightning Component. On Save button I’ve implemented the logic to hide the button after click.

Apex Controller:

public class SampleAuraController {
    
    @AuraEnabled
    Public static void createLead(Lead objLead){
        try{
            //Insert Lead Record
            insert objLead; 
        }catch(Exception e){
            //get exception message
            throw new AuraHandledException(e.getMessage());
        }
        finally {
        }
    } 
}

Lightning Component:

<!--Sample.cmp--> 
<aura:component controller="SampleAuraController" implements="flexipage:availableForAllPageTypes,force:appHostable">
    
    <!--Declare Attributes-->
    <aura:attribute name="isSpinner" type="boolean" default="false"/>
    <aura:attribute name="objLead" type="Lead" default="{'sobjectType':'Lead', 
                                                        'FirstName': '',
                                                        'LastName': '',
                                                        'Email': '', 
                                                        'Company': ''}"/>
    
    <!--Declare Handlers-->
    <aura:handler event="aura:waiting" action="{!c.handleShowSpinner}"/>
    <aura:handler event="aura:doneWaiting" action="{!c.handleHideSpinner}"/>
    
    <!--Component Start--> 
    <div class="slds-m-around--xx-large">
        <div class="container-fluid">
            <div class="form-group">
                <lightning:input name="fname" type="text" maxlength="50" required="true" label="First Name" value="{!v.objLead.FirstName}" />
            </div>
            <div class="form-group">
                <lightning:input name="lname" type="text" maxlength="50" required="true" label="Last Name" value="{!v.objLead.LastName}" />
            </div>
            <div class="form-group">
                <lightning:input name="emailId" type="email" maxlength="100" required="true" label="Email" value="{!v.objLead.Email}" />
            </div>
            <div class="form-group">
                <lightning:input name="company" type="text" maxlength="50" required="true" label="Company" value="{!v.objLead.Company}" />
            </div>
        </div>
        <br/>
        <lightning:button variant="brand" disabled="{!v.isSpinner}" label="{!v.isSpinner == true ? 'Saving...' : 'Save'}" onclick="{!c.handleLeadSave}" />             
    </div>
    <!--Component End-->
</aura:component>

Lightning JS Controller:

({
    //Handle Lead Save
    handleLeadSave : function(component, event, helper) {
        var objLead = component.get("v.objLead");
        var action = component.get("c.createLead");
        action.setParams({
            objLead : objLead
        });
        action.setCallback(this,function(a){
            var state = a.getState();
            if(state === "SUCCESS"){
                alert('Record is Created Successfully');
            } else if(state === "ERROR"){
                var errors = action.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        alert(errors[0].message);
                    }
                }
            }else if (status === "INCOMPLETE") {
                alert('No response from server or client is offline.');
            }
        });       
        $A.enqueueAction(action);
    },
    
    //Call by aura:waiting event  
    handleShowSpinner: function(component, event, helper) {
        component.set("v.isSpinner", true); 
    },
    
    //Call by aura:doneWaiting event 
    handleHideSpinner : function(component,event,helper){
        component.set("v.isSpinner", false);
    }
})

Output: