Thought Process behind this implementation
Use Case
In the Home Page User want to see the list of opportunities which has the profitability greater that 10% . The list of fields would be Name, Stage Name, Profitability, Close Date.
And the Same user want to see the list of opportunities in the Record Page , where only Closed Won opportunities will be shown. The list of fields would be Name, Type and Lead Source.
Expected Outcome
How Architecture works behind
1. Dynamically
Populated the List of Objects using Global class by extending
VisualEditor.DynamicPicklist.
2. Create
LWC component which Includes :
1. html File that will help
you to show the dynamic data table.
2. Java Script file that
will help you build the Logic.
3. Each Lightning web
component folder must include a configuration file named <component>.js-meta.xml.
In which there is attribute called "targetConfigs" help
you to Configure the component for different page types and define component
properties.
3. Create a class to prepare list
the data which needs to be shown based on certain attributes.
Process to implement
- As discussed First the Global class needs to created which will prepare and return the list of Object currently present in the Environment. Class name is ObjectList
Code as follows :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | global class ObjectList extends VisualEditor.DynamicPickList{ //Default method which can be ignored , kept that for your better understanding of stucture of VisualEditor Namespace global override VisualEditor.DataRow getDefaultValue(){ VisualEditor.DataRow defaultValue = new VisualEditor.DataRow('red', 'RED'); return defaultValue; } //Prepare the list of Object and return global override VisualEditor.DynamicPickListRows getValues() { Map <String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe(); VisualEditor.DynamicPickListRows objValues = new VisualEditor.DynamicPickListRows(); List<String> entities = new List<String>(schemaMap.keySet()); entities.sort(); for(String name : entities) { objValues.addRow( new VisualEditor.DataRow(name, name)); } return objValues; } } |
Few points to be remembered :
- In getValues method we preparing the list of object with the help of salesforce in-build method by extending the VisualEditor Namespace which provides classes and methods for interacting with the Lightning App Builder, in our POC we will be using it in meta.xml file in some time.
1 | global class ObjectList extends VisualEditor.DynamicPickList{ |
1 2 3 4 5 6 7 8 9 10 11 12 | global override VisualEditor.DynamicPickListRows getValues() { Map <String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe(); VisualEditor.DynamicPickListRows objValues = new VisualEditor.DynamicPickListRows(); List<String> entities = new List<String>(schemaMap.keySet()); entities.sort(); for(String name : entities) { objValues.addRow( new VisualEditor.DataRow(name, name)); } return objValues; } |
Another class needs to be created as follows :
All the functions has been described in comment section.
meta.xml file as follows :
Preview:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | /* Class Name : ReUsecls Developer Name : Avijit Das */ public with sharing class ReUsecls { public ReUsecls() { } /* Method Name : getFieldTypes Input Parameters : List of Columns Name, Object Name. OutPut Parameter : Map<String, List<String>> | Api Name=(data type,Label Name) | example : MainCompetitors__c=(STRING, Main Competitor(s)) purpose : It will taka Object and Columns name as input parameter and by using Schema.getGlobalDescribe preparing the Map as utput already given with the example. */ @AuraEnabled public static Map<String, List<String>> getFieldTypes(String selectedFields,String obj){ String objectName = obj; List<String> lst_str = new List<String>(); lst_str = selectedFields.split(','); Map<String, List<String>> fieldTypeMap = new Map<String, List<String>>(); for(String field : lst_str){ List<String> lst_objtypelab = new List<String>(); Schema.DisplayType fieldType = Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap().get(field).getDescribe().getType(); lst_objtypelab.add(String.valueOf(fieldType)); lst_objtypelab.add(String.valueOf(String.valueOf(Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap().get(field).getDescribe().getLabel()))); fieldTypeMap.put(field, lst_objtypelab); } return fieldTypeMap; } /* Method Name : getObjectRecords Input Parameters : List of Columns Name, Object Name, where contions OutPut Parameter : List<sObject> as it might be any object purpose : It will taka Object,Columns name and filtered conditions (optional) as input parameter and after forming the query retunr the list of records */ @AuraEnabled(cacheable=true) public static List<sObject> getObjectRecords(List<String> selectedFields,String obj,String whcon){ System.debug('Selected---'+selectedFields+'---'+obj); String stemp = ''; Integer i = 0; String query =''; for(String field : selectedFields){ if(i == 0){ stemp+= field; }else{ stemp+= ','+field; } i++; } query = 'SELECT ' + stemp + ' FROM '+obj; if(whcon!=''){ query = query+' where '+whcon; } return Database.query(query); } } |
All the functions has been described in comment section.
meta.xml file as follows :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>48.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> <target>lightning__RecordPage</target> <target>lightning__HomePage</target> </targets> <targetConfigs> <targetConfig targets="lightning__HomePage,lightning__RecordPage"> <property name="objName" type="String" datasource="apex://ObjectList" label="Object Name"/> <property name="fldShn" type="String" default="" label="Fields To be shown"/> <property name="whcon" type="String" default="" label="Condition"/> </targetConfig> </targetConfigs> </LightningComponentBundle> |
For this POC meta.xml file is pretty important. Points to be remembered :
- In targetConfigs target attribute we are specifying one or more page type where we will be using the component, In the POC we are trying to configure the component such a way that we can use it in Home page and record page as well.
1 | <targetConfig targets="lightning__HomePage,lightning__RecordPage"> |
- By Using the property attribute we are defining the input parameters for the Component author to be given at the time of adding the component in the Pages and based on the input parameter the component should work dynamically. There are three properties will be needed
- Object which will be pre-populated dynamically by using the visual editor and can be used by datasource attribute "datasource="apex://ObjectList""
- Number of fields which will reflect as column .
- Where condition, based on which we will be filtering the data.
<targetConfig targets="lightning__HomePage,lightning__RecordPage"> <property name="objName" type="String" datasource="apex://ObjectList" label="Object Name"/> <property name="fldShn" type="String" default="" label="Fields To be shown"/> <property name="whcon" type="String" default="" label="Condition"/> </targetConfig>
Js file as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /* Name : ReUse Developer Name : Avijit Das */ import { LightningElement, track, wire, api } from 'lwc'; import getObjectRecords from '@salesforce/apex/ReUsecls.getObjectRecords'; import getFieldTypes from '@salesforce/apex/ReUsecls.getFieldTypes'; export default class ReUse extends LightningElement { @api objName; @api fldShn; @api whcon; //default Id and Name will be assigned if nothing has been given. @track columns = [ { label: 'Id', fieldName: 'Id' }, { label: 'Name', fieldName: 'Name' } ]; //Passing the default columns @track selected = ['Id', 'Name']; @track fetchedRecords = []; //based on the chnages in the input parameters in the Meta.xml file the functions will fire @wire(getObjectRecords, { selectedFields: '$fldShn', obj: '$objName', whcon: '$whcon'}) wiredContacts({ error, data }) { if (data) { this.fetchedRecords = data; //This will prepare the list of columns this.handleFetchFieldTypes(); } else if (error) { console.log(error); } } handleFetchFieldTypes() { var fieldarry = this.fldShn.split(','); this.selected.splice(0, this.selected.length) //Prepare the input in the form of string array for (var j = 0; j < fieldarry.length; j++) { console.log(fieldarry[j]); this.selected.push(fieldarry[j]); } //once the functions has been called it will return Map<String, List<String>> getFieldTypes({ selectedFields: this.fldShn, obj: this.objName}) .then(result => { this.columns = this.selected.map(field => { //assigning the data type const dType = result[field][0]; //assigning the lable const dlabel = result[field][1]; if (dType === 'STRING' || dType === 'ID') { return { label: dlabel, fieldName: field }; } else if (dType === 'DATE') { return { label: dlabel, fieldName: field, type: 'date' }; } else if (dType === 'DATETIME') { return { label: dlabel, fieldName: field, type: 'datetime' }; } else if (dType === 'Integer') { return { label: dlabel, fieldName: field, type: 'Integer' }; } else if (dType === 'BOOLEAN') { return { label: dlabel, fieldName: field, type: 'text' }; } else { return { label: dlabel, fieldName: field }; } }); }) .catch(error => { console.log(error); }); } } |
html code as follows :
1 2 3 4 5 6 7 8 9 10 11 | <template> <lightning-card title="ReUsable Component" icon-name="custom:custom19"> <lightning-datatable key-field="id" data={fetchedRecords} columns={columns} > </lightning-datatable> </lightning-card> </template> |
Very useful article. I came to know something new on how to make a reusable component in LWC.
ReplyDeleteThanks....
Delete