Monday, March 6, 2017

Why to use design resource in Lightning bundle and how to add dynamic Options in datasource for Design Component

In Lightning Bundle, design resource helps in displaying components attributes in lightning app builder so that user can select attribute values and component behaves accordingly.

When to use design resource in lightning?


If you create a component which will be used in standalone lightning app, then you can pass attributes values for component and component will work accordingly but what if you component will be used in Lightning app builder while creating a lightning page. In this case how you will pass attributes values apart from default values.
So design resource helps you to specify some values to attributes which can be selected by Admin in lightning app builder. Below are 2 scenarios in which you should specify attributes in design resource otherwise they will not appear for users in Lightning App Builder.
  1. Required attributes which have default values
  2. Attributes which are not marked as required in component definition.
Let me explain this with an example.

I have created a component which display records from different objects. As of now for, I am going to display only record Id and name fields in table.

GenericListView.cmp

<aura:component controller="GenericListViewController"  implements="flexipage:availableForAllPageTypes" access="global" >
<aura:attribute name="objectName" type="String" default="Contact" required="true"/>
    <aura:attribute name="recList" type="List" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <aura:if isTrue="{!v.recList.length > 0}">
        <table class="slds-table slds-table--bordered slds-table--cell-buffer">
        <thead>
            <tr class="slds-text-title--caps">
            <th scope="col">RecordId</th>
            <th scope="col">Name</th>
            </tr>
        </thead>
        <aura:iteration items="{!v.recList}" var="item">
        <tr>
        <td> {!item.Id}</td>
            <td> {!item.Name}</td>
        </tr>
        </aura:iteration>
    </table>
    </aura:if>
</aura:component>

GenericListViewController.js

({
doInit : function(component, event, helper){
        var objname=component.get("v.objectName");
        //alert('objname:'+objname);
        var params ={}
        helper.callServer(
            component,
            "c.findRecords",
            function(response){
                //alert('Response from controller for opportunities:'+JSON.stringify(response));
                component.set("v.recList",response);
            },
            {objectName: objname}
        );
    }
})

GenericListViewHelper.js

({
callServer : function(component, method, callback, params) {
        //alert('Calling helper callServer function');
var action = component.get(method);
        if(params){
            action.setParams(params);
        }
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                callback.call(this,response.getReturnValue());
            }else if(state === "ERROR"){
                alert('Problem with connection. Please try again.');
            }
        });
$A.enqueueAction(action);
    }
})

GenericListViewController apex class

Global class GenericListViewController{
@auraEnabled
    public static List<sobject> findRecords(string objectName){
        string queryString ='';
        List<sobject> returnList=new List<sobject>();
        if(objectName !=null ){
    queryString='select Id, name from '+ objectName + '  Order by lastmodifiedDate DESC Limit 10';
        }else{
            queryString='select Id, name from Contact   Order by lastmodifiedDate DESC Limit 10';  
        }
        system.debug('**queryString:'+queryString);
        returnList=database.query(queryString);
    return returnList;
    }
}

Now if you use this component in Lightning app builder, then you will not get any option to specify "ObjectName" attribute value and component will take default value which is "Contact" as specified in component definition.

Now if you want that admin will get option to select ObjectName so that component will display records from that object, then add attribute in design resource. Below is sample code:

GenericListView.design

<design:component >
<design:attribute name="objectName" datasource="Contact,Account,Opportunity" />
</design:component>

After saving this file you will get option to select object name in app builder.

Note:
  1. What ever you specify in datasource seperated by comma will appear as dropdown in Lightning app builder.
  2. Design resource supports only text, boolean and int.

How to add dynamic options to datasource in design components?


You have to follow below steps to implement this:
  • Create a Apex class which will be used to provide dynamic values. Apex class must extend the VisualEditor.DynamicPickList abstract class.
  • Specify datasource as this apex class while creating attribute in design resorce.

GenericListViewController apex class

Global class GenericListViewController extends VisualEditor.DynamicPickList{
@auraEnabled
    public static List<sobject> findRecords(string objectName){
        string queryString ='';
        List<sobject> returnList=new List<sobject>();
        if(objectName !=null ){
    queryString='select Id, name from '+ objectName + '  Order by lastmodifiedDate DESC Limit 10';
        }else{
            queryString='select Id, name from Contact   Order by lastmodifiedDate DESC Limit 10';  
        }
        system.debug('**queryString:'+queryString);
        returnList=database.query(queryString);
    return returnList;
    }
    global override VisualEditor.DataRow getDefaultValue(){
        VisualEditor.DataRow defaultValue = new VisualEditor.DataRow('contact', 'Contact');
        return defaultValue;
    }
    global override VisualEditor.DynamicPickListRows getValues() {
        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
        VisualEditor.DynamicPickListRows  myValues = new VisualEditor.DynamicPickListRows();
        VisualEditor.DataRow value1 = new VisualEditor.DataRow('Contact', 'Contact');
        myValues.addRow(value1);
        VisualEditor.DataRow value2 = new VisualEditor.DataRow('Account', 'Account');
        myValues.addRow(value2);
        VisualEditor.DataRow value3 = new VisualEditor.DataRow('Lead', 'Lead');
        myValues.addRow(value3);
        //Or you use object describe ti find all object details
        /*for(String ss1: schemaMap.keyset()){
            Schema.SObjectType objToken=schemaMap.get(ss1);
            Schema.DescribeSObjectResult objDescribe=objToken.getdescribe();
            VisualEditor.DataRow value11 = new VisualEditor.DataRow(objDescribe.getLabel(), objDescribe.getName());
            myValues.addRow(value11);
        }
*/
        return myValues;
    }
}

In this class, I am specifying Contact, Account and Lead object. You can use object describe if you want to display all object name from your org or you can add any values.

Modify you GenericListView.design code as shown below:

<design:component >
<design:attribute name="objectName" datasource="apex://GenericListViewController"/>
</design:component>

Now if you use this component in Lightning app builder then, you will get Contact, Account and Lead as Object name attribute options;



In this way you can pass values from apex class to datasource in design attributes.

Hope this will help!!!

Looking forward for everyone feedback..


More Blogs>>: 
DYNAMICALLY CREATING AND DESTROYING LIGHTNING COMPONENTS    
RAISING AND HANDLING CUSTOM EVENTS IN sALESFORCE lIGHTNING    
DYNAMIC APEX IN SALESFORCE    
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IT IN SALESFORCE    

5 comments:

  1. Hi...Sunil design is not showing ....lyk ur stuff...only showing id , name...

    ReplyDelete
    Replies
    1. Hi Jagannath,

      In order to see design attributes, you need to create app page using lightning app builder and add this component, then you will see option to set design parameters.

      In Table, I am displaying only 2 columns ids and name. You can customize as per your requirement.

      Let me know if it answer your question. If no then share some more details about issue your are facing.

      Regards,
      Sunil Kumar

      Delete
  2. Thank you so much I got it...Good Work

    ReplyDelete