A blog dedicated to Salesforce Ohana

Dynamic Apex - Sky is The Limit - Explained with Example


Today I am going to explain Dynamic Apex with examples. Dynamic Apex will help developer to create more flexible and robust application because with the help of Dynamic Apex, developer can access the sObject and field describe information, access Salesforce application information. Another great help is that with Dynamic Apex, developer can now write dynamic SOQL, SOSL and DML statements. So basically with dynamic apex, you have the magic wand in your hand.


So without any further delay, let's start the power of magic wand.

Basics of Apex Describe:
In order to get information about sObjects in Salesforce, you have two options - either use tokens or use describeSObjects Schema methods.

Apex provides two data structures and a method for fetching information about sObjects and fields. They are listed below -
  • Token - This is a lightweight, serializable reference to an sObject or a field that is validated at run time. Since they are lightweight, using them make your code faster and more efficient.
  • The describeSObjects method - This method from the Schema class will perform the describe on sObject Types.
  • Describe result - This is basically the object of  type Schema.DescribeSObjectResult which holds the result i.e. contains all the describe properties for the sObject or field. These objects are not serializable and validated always at runtime. 
Let's get into more details before we jump into the examples -
Schema Describe -
  • Schema Describe is a way to programmatically learn about the metadata of your datamodel.
  • Schema Describe calls provides the ability to describe the information about the current org schema such as list of top level objects including custom objects and their fields.
         

Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Schema Class -
Schema class comes with few static methods which are very important. Below are they -
  • getGlobalDescribe() - This method will return a map of all sObject names (keys) to sObject tokens (values) for the standard as well as custom objects present in the organization.
  • describeDataCategoryGroups(List) - This method will return a list of the category groups associated with the specified objects.
  • describeSObjects(List) - Describes the metadata (field list and object properties) for the specified objects or the array of objects.
  • describeTabs() - Returns the information about standard and custom apps available to the running user.
Schema Namespace -
The Schema Namespace provides classes and methods for getting schema metadata information. Below are the classes -
  • ChildRelationship class - This class contains the methods for accessing the child relationship as well as child sObject for a parent sObject.
  • DescribeFieldResult class - Contains methods for describing fields.
  • DescribeSObjectResult class -Contains methods for describing sObjects.
  • DescribeTabResult class - Returns tab metadata information for a tab in a standard or custom app available.
  • FieldSet class - This contains methods for discovering and retrieving the details of field sets created on sObjects.
  • SObjectField class - This is the return type of getSObjectField method,which basically returns the object of type Schema.SObjectField class.
  • SObjectType class - This is the return type of getSObjectType method,which basically returns the object of type Schema.SObjectType class.
  • RecordTypeInfo class - This contains the methods for accessing record type information associated with a sObject.
  • PicklistEntry class - This represents a picklist entry.
You can get more details about the Schema Namespace class @ 

Now let's play with Dynamic Apex -

Apex code to fetch all objects (Standard as well as Custom) from an organization -
VF Page ::
<apex:page controller="ObjectRetrievePractice">
    <apex:form id="TheForm">
        <apex:pageBlock title="All Objects Fetched Dynamically">
            <apex:outputLabel value="All Objects ">
                <apex:selectList size="1">
                    <apex:selectoptions value="{!allObjNames}"></apex:selectoptions>
                </apex:selectList>
            </apex:outputLabel>
        </apex:pageBlock> 
    </apex:form>
</apex:page>
Controller ::
public with sharing class ObjectRetrievePractice {
    //Method to fetch all objects present in the org
    public List<SelectOption> getAllObjNames(){
        //Get all Object names
 List<Schema.SObjectType> gd = Schema.getGlobalDescribe().Values();
  
 List<SelectOption> options = new List<SelectOption>();
 options.add(new SelectOption('--None','--None--'));
  
 for(Schema.SObjectType f : gd){
       options.add(new SelectOption(f.getDescribe().getName(),f.getDescribe().getName()));
 }
        return options;
    }
}

Apex code to fetch all Custom objects only from an organization -
VF Page ::
<apex:page controller="ObjectRetrievePractice">
    <apex:form id="TheForm">
        <apex:pageBlock title="All Custom Objects Fetched Dynamically">
            <apex:outputLabel value="All Custom Objects ">
                <apex:selectList size="1">
                    <apex:selectoptions value="{!allCustomObjNames}"></apex:selectoptions>
                </apex:selectList>
            </apex:outputLabel>
        </apex:pageBlock>
    </apex:form>
</apex:page>
Controller ::
public with sharing class ObjectRetrievePractice {
    //Method to fetch only custom objects from the org
    public List<SelectOption> getAllCustomObjNames(){
        //Get all Object names
        List<Schema.SObjectType> gd = Schema.getGlobalDescribe().Values();
        
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('--None','--None--'));
        
        for(Schema.SObjectType f : gd){
            if(f.getDescribe().isCustom())
                options.add(new SelectOption(f.getDescribe().getLabel(),f.getDescribe().getLabel()));
        }
        return options;
    }
}

Apex code to fetch all fields dynamically from an Object -
VF Page ::
<apex:page controller="ObjectRetrievePractice">
    <apex:form id="TheForm">
        <apex:pageBlock title="All Fields from Account Object">
            <apex:outputLabel value="All Account Fields ">
                <apex:selectList size="1">
                    <apex:selectoptions value="{!allAccountFields}"></apex:selectoptions>
                </apex:selectList>
            </apex:outputLabel>
        </apex:pageBlock>
    </apex:form>
</apex:page>
Controller ::
public with sharing class ObjectRetrievePractice {
    //Method to fetch Account fields dynamically
    public List<SelectOption> getAllAccountFields(){
        List<SelectOption> options = new List<SelectOption>();
        
        Map<String, Schema.SObjectField> fm = Schema.SObjectType.Account.fields.getMap();
        
        for(String token : fm.keyset()){
            options.add(new SelectOption(fm.get(token).getDescribe().getLabel(),fm.get(token).getDescribe().getLabel()));
        }
        return options;
    }
}

Now a little advance code snippet.
Apex code to first select the Object and then dynamically fetch fields from that object -
VF Page ::
<apex:page controller="ObjectRetrievePractice">
    <apex:form id="TheForm">
        <apex:pageBlock >
            <apex:pageBlockSection title="Select an Object" collapsible="false" columns="2">
                 <apex:pageBlockSectionItem >
                     <apex:outputLabel value="Select an object:"></apex:outputLabel>
                     <apex:selectList value="{!objectName}" size="1" multiselect="false">
                         <apex:selectOptions value="{!allObjNames}">
                         </apex:selectOptions>
                         <apex:actionSupport action="{!fetchFields}" event="onchange" reRender="fieldsPanel"/>  
                     </apex:selectList>
                 </apex:pageBlockSectionItem>
                 
                 <apex:pageBlockSectionItem >
                 <apex:outputPanel id="fieldsPanel">
                     <apex:outputLabel value="Select Fields:"> </apex:outputLabel>
                     <apex:selectList value="{!fields}" multiselect="true" size="3" >
                         <apex:selectOptions value="{!lsps}">
                         
                         </apex:selectOptions>
                     </apex:selectList>
                     </apex:outputPanel>
                 </apex:pageBlockSectionItem> 
             </apex:pageBlockSection>
         </apex:pageBlock>
    </apex:form>
</apex:page>
Controller ::
public with sharing class ObjectRetrievePractice {
    public String objectName { get; set; } 
    public list<SelectOption> lsps{get;set;}  
    public String fields { get; set; }
    
    //Method to fetch all objects present in the org
    public List<SelectOption> getAllObjNames(){
        //Get all Object names
  List<Schema.SObjectType> gd = Schema.getGlobalDescribe().Values();
  
  List<SelectOption> options = new List<SelectOption>();
  options.add(new SelectOption('--None','--None--'));
  
  for(Schema.SObjectType f : gd){
      options.add(new SelectOption(f.getDescribe().getName(),f.getDescribe().getName()));
  }
  return options;
 }
    
    //Method to fetch fields dynamically from the selected objects  
    public void fetchFields() {
        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
        lsps = new List<SelectOption>();
        
        if(objectName!=null || objectName!=''){
            Map<string,Schema.SObjectField> mpConField=schemaMap.get(objectName).getDescribe().fields.getMap();
            
            for(String token : mpConField.keyset()){
             lsps.add(new SelectOption(mpConField.get(token).getDescribe().getLabel(),mpConField.get(token).getDescribe().getLabel()));
            }
        }        
    }
}

Apex code to select required fields from Account Object -
In Dynamic Apex, we don't have any direct method available which can tell us whether a field is required or not. But there is another way to find it out. If any field satisfies below three properties, then it is a required field
  • If the field is createable
  • If the field is not nillable and
  • If the field does not have any default value.
Below code will show how we can find only the required fields from Account object

VF Page ::
<apex:page controller="ObjectRetrievePractice">
    <apex:form id="TheForm">
        <apex:pageBlock title="Display only the required fields Account Object">
            <apex:outputLabel value="All Required Fields from Account object ">
                <apex:selectList size="1">
                    <apex:selectoptions value="{!allAccountRequiredFields}"></apex:selectoptions>
                </apex:selectList>
            </apex:outputLabel>
        </apex:pageBlock>
    </apex:form>
</apex:page>
Controller ::
public with sharing class ObjectRetrievePractice {
    //Method to fetch Required fields from Account object dynamically
    public List<SelectOption> getAllAccountRequiredFields(){
        List<SelectOption> options = new List<SelectOption>();
        
        Map<String, Schema.SObjectField> fm = Schema.SObjectType.Account.fields.getMap();
        
        for(String token : fm.keyset()){
            Schema.DescribeFieldResult describeResult = fm.get(token).getDescribe();
            if(describeResult.isCreateable() && !describeResult.isNillable() && !describeResult.isDefaultedOnCreate()){
                options.add(new SelectOption(describeResult.getLabel(),describeResult.getLabel()));
            }
        }
        return options;
    }
}

Apex code to get Child Relationship from an object -
You can access the child relationship from a parent sObject and also the child sObject using the ChildRelationship object method.

A ChildRelationship object will be returned when you call the method getChildRelationship().
VF Page ::
<apex:page controller="ObjectRetrievePractice">
    <apex:form id="TheForm">
        <apex:pageBlock title="Display Account's Child Objects">
            <apex:outputLabel value="Child Objects from Account ">
                <apex:selectList size="1">
                    <apex:selectoptions value="{!allAccountChildObjects}"></apex:selectoptions>
                </apex:selectList>
            </apex:outputLabel>
        </apex:pageBlock>
    </apex:form>
</apex:page>
Controller ::
public with sharing class ObjectRetrievePractice {
    //Method to fetch Child Relationship from Account object dynamically
    public List<SelectOption> getAllAccountChildObjects(){
        List<SelectOption> options = new List<SelectOption>();
        
        Schema.DescribeSObjectResult describeResult = Account.SObjectType.getDescribe();
        List<Schema.ChildRelationship> lstchildrelationships = describeResult.getChildRelationships();
        
        for(Schema.ChildRelationship relname:lstchildrelationships){
             options.add(new SelectOption(relname.getChildSObject().getDescribe().getLabel(),relname.getChildSObject().getDescribe().getLabel()));
        }
        
        return options;
    }
}

Apex code to fetch/display Trigger Names of selected object -
List<String> triggerName = new List<String>();
               
Schema.DescribeSObjectResult result = Account.sObjectType.getDescribe();
for(ApexTrigger aptrig:[select id,name,Status,TableEnumOrId from apextrigger where TableEnumOrId=:result.getName()]){
    triggerName.add(aptrig.name);
}
System.debug('--Trigger Names :: '+triggerName);



Apex code to fetch Record Type ID without SOQL -
We can use getRecordTypeInfosByName() method to get the record type ids without using SOQL. This will help us to reduce the SOQL operation in the code.

Schema.DescribeSObjectResult result = Account.sObjectType.getDescribe();
//Getting all Recordtype from Account object
if(result.getRecordTypeInfosByName() != null) {
    Map<String,Schema.RecordTypeInfo> recordTypeInfo = result.getRecordTypeInfosByName();
    System.debug('-- recordTypeInfo:: '+recordTypeInfo);
 //Getting  Telecom Record Type Id. I have this record type in my org
 if(recordTypeInfo.containsKey('Telecom')) {
  Id rtId = recordTypeInfo.get('Telecom').getRecordTypeId();
  system.debug('-- Record Type id:: '+rtId);
 }   
}

With all the above code snippets, I hope you already realized the power of Dynamic Apex. So please go ahead and play as much as your want. Sky is the limit here.

I will really appreciate if you provide me your valuable feedback. Thanks.
Share:

"Lightning Design System" Series || Part 1 || Introduction and Setup your environment to build Visualforce Page with Lightning Design System


The Salesforce User Experience team has come up with a great UI framework called Lightning Design System. The intention is to build application, visualforce pages with this framework which will comply with the new Salesforce lightning look and feel. And the best part is that you don't need to play with CSS.

Now you probably started thinking why I should go for this new Lightning Design System when I have Twitter Bootstrap or Foundation with which also I can achieve the same. The reason is very simple and they are as follows -
  • With the use of this new Lightning Design System, your application or visualforce page will comply with the new Salesforce look and feel.
  • It is a new design system and it is getting improved every day. So as long as you are referring the latest version of design system, you are getting most out of this new framework.
  • The CSS is fully namespaced with slds- prefix which will avoid CSS conflicts.
Ingredients of the Framework:
Salesforce Lightning Design System framework comes with four types of resources.
  • CSS Framework: This will contain UI components, such as page headers, form elements, buttons, grid layout system. This will come up with a single purpose helper class which will assist with spacing, sizing and other visual adjustments.
  • Icons: Includes action, custom, standard and utility icons both in PNG and SVG format.
  • Font: Salesforce designed a new font - Salesforce Sans font. This font is available here.
  • Design Tokens: These are simple variables which will help you design pages, application matching your brand. 
Usage of the Framework:
You can use this framework in -
  • Visualforce pages. (You don't need Lightning Experience enabled in your org for this).
  • Lightning pages and components
  • Mobile apps.
  • Standalone web apps.
Ok enough of theory.

Let's start preparing our environment, so that we can play around.
Before we even start we need to install Lightning Design System as static resource. To use this framework in visualforce page, you need to create a CSS file with a custom scoped outer wrapper. Don't worry. Salesforce comes up with CSS Customizer tool for this. You can use that by following the below steps -
  • Click on Design System CSS Customizer Tool.
  • Choose the Salesforce release and scoping class. You need to remember the class name as you are going to refer the same during visualforce page development.
  • Once done, upload the zipped file as static resource in Salesforce. Please name it SLDSXXX where XXX is the version. The day when I am writing this blog post, the latest version is 2.0.3. So my static resource name is SLDS203.
  • Done.
Let's write our first Visualforce page:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<apex:page showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <head>
            <title>Salesforce Lightning Design System Trailhead Module</title>
            <apex:stylesheet value="{!URLFOR($Resource.SLDS203,'assets/styles/salesforce-lightning-design-system-vf.css')}"/>
        </head>
        
        <body>
            <div class="suddeb">
                <p class="slds-text-heading--label slds-m-bottom--small">
                    Salesforce Lightning Design System Trailhead Module
                </p>
            </div>
        </body>
    </html>
</apex:page>
After saving this visualforce page, if you execute, you will see that the look and feel in as per the new Salesforce look and feel. Awesome.

Let's now understand the important stuffs here -
  • Line# 3: To use Salesforce Lightning Design System, you need to make sure that you are including the below attribute in html tag, which will enable support for SVG icon sprite maps within Visualforce.
  • Line# 2: We are turning off header, sidebar and built in stylesheet. With this turned on, you can't add extra attribute in html tag(specified above), which means SVG will not be supported.
  • Line# 6: This is the step/way how you are including lightning design system stylesheet from static resource. This is very important to make sure lightning design system CSS stuffs are available in your visualforce page.
  • Line# 10: To use Lightning Design System markup in visualforce page, it should be placed inside an outer wrapper
    with scoping class you created using CSS Customizer tool. In my case,  the name of the scoping class is: "suddeb". 
  • Don't worry about Line# 11 for the time being. I will explain the same in my next post.
Great. So we have created our first visualforce page with Lightning Design System. In my next post, I will get into more details. Till then, please provide your feedback. Thanks.

Share:

Follow Me

Enter your email address:

Delivered by FeedBurner

Popular Posts

Labels

Salesforce (105) Apex (44) admin (27) ADM (20) visualforce (20) dev 501 (19) integration (18) learn salesforce (18) 501 (16) SOAP (13) lightning (12) tutorial (11) Certification. (9) javascript (8) Trigger (7) test class (7) unit testing (7) Sharing and Visibility (6) design pattern (6) report (6) security (6) trailhead (6) Advanced Admin (5) Certification (5) New Features (5) SOQL (5) css (5) dashboard (5) debug (5) developer (5) formula (5) mobile (5) salesforce release (5) service cloud (5) solution management (5) use case (5) JSON (4) Kitchener Developer Group (4) Lightning Experience (4) WebSphere (4) best practice (4) cast iron (4) component (4) deployment (4) github (4) html (4) polymer (4) profiles (4) responsive (4) tdd (4) ui (4) Advanced Apex (3) Architect (3) Live Chat (3) Performance (3) Products (3) Role (3) Sales Cloud (3) Salesforce DX (3) Scratch Org (3) Study Notes. (3) Summer15 (3) Tips (3) Web Technology (3) dynamic apex (3) event (3) license (3) map (3) mapbox (3) singleton (3) version controlling (3) Bulkify (2) Data Architecture and Management Certification (2) Distributed Version Controlling (2) ES6 (2) Eclipse (2) Einstein (2) Enterprise Territory Management (2) Financial Services Cloud (2) Force.com IDE (2) Governor Limit (2) Groups (2) IBM (2) Implicit Sharing (2) JourneyToCTA (2) Lightning Design System (2) Live Agent (2) Metadata (2) Online Event (2) Opportunity (2) Price Book (2) REST (2) SOSL (2) Sharing (2) Spring 15 (2) Summer17 (2) Territory (2) ant (2) automation tool (2) basic (2) chatter (2) coding (2) communication (2) console (2) controller (2) documentation (2) flow (2) git (2) jquery (2) logging (2) object (2) permission (2) process builder (2) release (2) salesforce1 (2) strategy (2) xml (2) Action Plan (1) Action Plan Template (1) Agent Productivity (1) Analytics (1) Apex Sharing (1) Arrow (1) Asynchronous callout (1) Aura Framework (1) Bots (1) Browser (1) Bulk data load (1) CTA (1) Calendar (1) Canon (1) Case Management (1) Cheat Sheet (1) Classic (1) Community (1) Constructor (1) Contact Center (1) Continuation (1) Continuous Integration (1) Convert (1) Cookie (1) Custom Metadata (1) Custom Object (1) Customer (1) Decorator Design Pattern (1) Dev Hub (1) Devops (1) Diwali (1) Email (1) FSC (1) Function (1) Goals (1) Guide (1) Household (1) Ideas (1) Improvement (1) KPIs (1) Kitchener User Group (1) Large Data Volume (1) LastModifiedDate (1) Lightning Web Component (1) Manual Sharing (1) Metrics (1) New (1) OOPS (1) OWD (1) Omni-Channel (1) Partner (1) Person Account (1) Photo (1) Platform Developer I (1) Presentation (1) Product Schedule (1) Profile (1) Promise (1) Prototype (1) Public Site (1) Query Plan (1) QuickReference (1) Reports (1) Retrieve (1) Role Hierarchy (1) SFDX (1) Salesforce Optimizer (1) Session (1) Sharing Rule (1) Sharing Sets (1) Site (1) Skills (1) Snap-ins (1) Spring 17 (1) Summer14 (1) Summer16 (1) Switch (1) SystemModStamp (1) User License (1) Users (1) Webservice (1) Winter'15 (1) Winter'17 (1) access (1) agile (1) app (1) approval process (1) aura (1) awesome (1) backup (1) bitbucket (1) book (1) campaign (1) change set (1) code (1) code coverage (1) configuration (1) csv (1) custom button (1) custom settings (1) customization (1) data loader (1) database (1) delegate Admin (1) describe (1) dom (1) dreamforce (1) duplicate (1) dynamic (1) equals (1) error (1) field-level security (1) folder (1) ftp (1) generic (1) gift (1) global describe (1) hashcode (1) import wizard (1) jenkins (1) keynote (1) long running requests (1) monitoring (1) mysql (1) page layout (1) personal (1) power of one (1) record type (1) relationship (1) request (1) review (1) sub-tab (1) tab (1) username (1) visual workflow (1) workflow (1)

Total Subscribers

Total Pageviews