Lightning Series 3 – Building a Simple Lightning App to View, Edit and Delete Records

In our previous series, we have talked about searching and inserting new records using lightning components. In this blog, we gonna talk about how we can view, edit and delete the records in lightning experience.

VIEW, EDIT AND DELETE RECORD FROM THE LIST OF RECORDS DISPLAYED IN TABLE

StaffView

We need to create below three elements to build the complete functionality:

  1. Apex Class
  2. Lightning Component
  3. JS controller

Apex Class:

Below apex class has different methods invoked based on the action required from user like viewing, updating and deleting the records.  @AuraEnabled enables you to access this method in lightning component.

/************************************************************

Name: CreatestaffRecord
Type: Apex Class  
Purpose: Apex Class  for  lightning component 
CreatestaffRecordController.cmp
***********************************************************/
public with sharing class CreateStaffRecord {
    
    @AuraEnabled
    public static void updateRecord(Staff__c staff){
        try{
            update staff;
        }catch(DMLException e){
            throw new AuraHandledException(e.getDMLMessage(0)); 
        }catch(Exception e){
            throw new AuraHandledException(e.getMessage()); 
        }       
    }  
    
    @AuraEnabled
    public static Staff__c deleteRecord(Staff__c staff){
        try{
            if(staff != null){
                delete staff;
            }
        }catch(DMLException e){
            throw new AuraHandledException(e.getDMLMessage(0)); 
        }catch(Exception e){
            throw new AuraHandledException(e.getMessage()); 
        }  
        return staff;
    }
}

Lightning Component:

Let’s hit on the ground and create a component to view, edit and delete a record of  Staff.

Please click here to view the code:

JS Controller:

StaffRecordViewController.js

({
    doInit : function(component){
        
        // Get a reference to the getWeather() function defined in the Apex controller
        var action = component.get("c.getStaffRecord");
        action.setParams({
            "staffId": component.get("v.recordId")
        });
        // Register the callback function
        action.setCallback(this, function(response){
            // Set the component attributes using values returned by the API call
            if (response.getState() == 'SUCCESS') {
                var staff=response.getReturnValue();
                
                component.set("v.staff", staff);
                component.set("v.isEditMode", false);
            }
        });
        // Invoke the service
        $A.enqueueAction(action);
    },
    
    handleStaffEvent : function(component, event) {
        var recId = event.getParam("recordId");
        // set the handler attributes based on event data
        component.set("v.recordId", recId);

        var action = component.get('c.getStaffRecord');
        
        action.setParams({"staffId": recId});
        
        action.setCallback(this, function(response){
            
            if (response.getState() == 'SUCCESS') {
                
                
                var staff=response.getReturnValue()
                component.set("v.staff", staff);
                
                component.set("v.isEditMode", false);
            }
        });
        $A.enqueueAction(action);   
       
    },
    editStaff : function(component){        
        component.set("v.isEditMode",true);
    },
    cancelPage : function(component){        
        component.set("v.isEditMode",false);
    },    
    saveStaff : function(component, event, helper){
        // Get a reference to the updateRecord() function defined in the Apex controller
        //getting the staff information
        var staff = component.get("v.staff");       
        
        //Make field required from front end (Not from DB)
        if(staff.Last_Name__c==''){
            alert('Missing Last name');
            return false;
        }
        
        
        var action = component.get("c.updateRecord");
        action.setParams({
            staff : staff
        });
        // Register the callback function
        action.setCallback(this, function(response){
            var state = response.getState();
            
            // Set the component attributes using values returned by the API call
            if (state == "SUCCESS") {
                    
                component.set("v.staff", staff);
                
                component.set("v.isEditMode", false);
               
            }else if(state == "ERROR"){
                //errors coming from DB thrown by controler catch blocl
                let errors = response.getError();
                let message;
                // Retrieve the error message sent by the server
                if (errors && Array.isArray(errors) && errors.length > 0) {
                    message = errors[0].message;
                }
                
                alert(message);
            }
        });
        // Invoke the service
        $A.enqueueAction(action);
    },
    
    delStaff : function(component, event, helper){
        // Get a reference to the updateRecord() function defined in the Apex controller
        //getting the staff information
        var staff = component.get("v.staff");        
        var action = component.get("c.deleteRecord");
        action.setParams({
            staff : staff
        });
        
        // Register the callback function
        action.setCallback(this, function(response){
            // Set the component attributes using values returned by the API call
            if (response.getState() == 'SUCCESS') {
                component.set("v.staff", staff);
                component.set("v.isEditMode", false);
            }
        });
        
        
        // Invoke the service
        $A.enqueueAction(action);
        alert("Record is deleted.");
        
        var urlEvent = $A.get("e.force:navigateToURL");
        urlEvent.setParams({
            "url": "/a00/o"
        });
        
        urlEvent.fire();
    }
})     
    

Lightning Series 2 – Building Simple Lightning App to insert a record

Salesforce Lightning is a component-based framework for application development. A Developer can build responsive applications for any device using lightning which include an out-of-the-box set of components, event-driven architecture, and a framework optimized for performance.

The Lightning Component framework is a UI framework for developing dynamic web apps for mobile and desktop devices. It uses JavaScript on the client side and Apex on the server side.

Let’s find out how we can build an interface to insert record to database on Lighting.

INSERT RECORD USING LIGHTNING COMPONENT

createstafflightning

We need to create below three elements to build the complete functionality:

  1. Apex Class
  2. Lightning Component
  3. JS controller

Apex Class:

In the above code, we have used @AuraEnabled annotation which enables client- and server-side access to an Apex controller method. Providing this annotation makes your methods available to your Lightning components.

 public with sharing class CreateStaffRecord {
    
/**
* Create a new staff Record
* @param Staff__c staff  staff record to be inserted
*/
    @AuraEnabled
    public static Staff__c createRecord(Staff__c staff){
        try{
            insert staff;
            
        }catch(DMLException e){
            throw new AuraHandledException(e.getDMLMessage(0)); 
        }catch(Exception e){
            throw new AuraHandledException(e.getMessage()); 
        }
        return staff;
    }

Lightning Component:

Let’s hit on the ground and create a component to insert a new record for  Staff.  There are some steps we need to follow before creating a lightning component. The Developer Console is a convenient, built-in tool we can use to create new and edit existing Lightning components and other bundles.

  1. Enable My domain.
  2. Open the Developer Console.
    Select Developer Console from the Your Name or the quick access menu (Setup gear icon).
    1. Open the New Lightning Bundle panel for a Lightning component.
      Select File | New | Lightning Component.
    2. Name the component CreateStaffRecord.
    3. Click Submit to create the component
    4. Inside the code window, use the below code and we will discuss about this code in detail:

Please click here to view the code:

In the above code, we have used below tags and the explanation is written for each of these tags:

Links:

({

create : function(component, event, helper) {
//getting the staff information
var staff = component.get(“v.staff”);

//Make field required from front end (Not from DB)
if(staff.Last_Name__c==”){
alert(‘Missing Last name’);
return false;
}

//Calling the Apex Function
var action = component.get(“c.createRecord”);

//Setting the Apex Parameter
action.setParams({
staff : staff
});

//Setting the Callback
action.setCallback(this,function(response){
//get the response state
var state = response.getState();
//check if result is successfull
if(state == “SUCCESS”){
//Reset Form
var newstaff = {‘sobjectType’: ‘staff__c’,’First_Name__c’: ”,
‘Last_Name__c’: ”,’Email__c’: ”,’Phone__c’: ”,’Start_Date__c’:”
};
//Resetting the Values in the form
component.set(“v.staff”,newstaff);

alert(‘Record is Created Sucessfully’);

var urlEvent = $A.get(“e.force:navigateToURL”);
urlEvent.setParams({
“url”:”/lightning/o/Staff__c/list?filterName=Recent&0.source=alohaHeader”
});
console.log(urlEvent);
urlEvent.fire();

} else if(state == “ERROR”){
//errors coming from DB thrown by controler catch blocl
let errors = response.getError();
let message;
// Retrieve the error message sent by the server
if (errors && Array.isArray(errors) && errors.length > 0) {
message = errors[0].message;
}

alert(message);
}
});
//adds the server-side action to the queue
$A.enqueueAction(action);

}
})


 

Lightning Series 1 – Building a Simple Lightning App to Search and list Records

Let’s start searching and listing records through lightning components. We used to create tables using pageBlockTable in visualforce pages. In lightning, we either use HTML tables or inbuilt component tags like (lightning:datatable) to display the data in rows and columns format. Data tables are an enhanced version of an HTML table and are used to display tabular data. Here in this example, we use html table to display the data which enhance the user interface and speed up the searching and retrieve the relevant data. We are using SLDS library with HTML tags to support the CSS styles provided by Salesforce.

SLDS Library

https://www.lightningdesignsystem.com/components/overview/

Data Table

https://www.lightningdesignsystem.com/components/data-tables/

SEARCH AND DISPLAY RECORDS USING LIGHTNING COMPONENT

searchPage.PNG

Here is the order of execution of a lightning component:

Lightning Component invokes JSController, which further invokes the APEX Class. The Lightning Component can’t directly communicate with the APEX Class. It has to be always invoked via JSController.

How Lightning Component communicates with controllers or vice versa ?

The syntax “v.” is used to get and set the value of the Lightning Component variable from JSController.

“c.” is used to invoke controller methods or access variables. If “c.” is used on the Lightning Component, this means we are accessing JSContoller variables/methods. If “c.” is used in the JSController, then we are accessing APEX Class variables/methods.

Building Search and List Component

Let’s build a search and list Lighting Component. We need to create below six items to build this search functionality:

  1. Apex Class
  2. Lightning Component
  3. JS Controller
  4. Event
  5. Lighting Tab
  6. Lightning App

Apex Class

Below apex class returns the list of staff based on the name entered on the search box displayed on the component. @AuraEnabled enables you to access this method in lightning component.

searchStaffController.apxc

public class searchStaffController {
    @AuraEnabled
    public static List  fetchStaff(String searchKeyWord) {
        String searchKey = searchKeyWord + '%';
        List  returnList = new List  ();
        List  lstOfStaff = [select Id, Name,First_Name__c, Middle_Name__c, Last_Name__c,Phone__c,Email__c,Status__c from Staff__c where First_Name__c LIKE: searchKey OR Last_Name__c LIKE: searchKey];
        
        System.debug('Staff **** ' + lstOfStaff);
        
        
        for (Staff__c staff: lstOfStaff) {
            returnList.add(staff);
        }
        return returnList;
    }
}

Lightning Component:

Lightning Component acts like a visualforce page which displays all the components required to get inputs from user and display the output. This component contains search box, buttons , and data tables to display the relevant records.

There are some steps we need to follow before creating a lightning component. The Developer Console is a convenient, built-in tool we can use to create new and edit existing Lightning components and other bundles.

  1. Enable My domain.
  2. Open the Developer Console.
    Select Developer Console from the Your Name or the quick access menu (Setup gear icon).
    1. Open the New Lightning Bundle panel for a Lightning component.
      Select File | New | Lightning Component.
    2. Name the component SearchStaff.
    3. Click Submit to create the component
    4. Inside the code window, use the below code and we will discuss about this code in detail:

Please click here to view the lightning component code: searchStaff.cmp

JS Controller:

This controller is client based java script controller which invokes the actions driven by component and further invokes apex class ‘s method to search staff records. In the below code, we have three parameters like component, event, helper which stores the information of component variables, event and associated apex class method info.

This is a client-side controller handles events within a component. It’s a JavaScript resource that defines the functions for all of the component’s actions.
Please follow the steps below to create JS controller:
1) In the developer console, we need to open the staff component.
2) we can simply press Ctrl + Shift + 2 or double click on the “CONTROLLLER” on the right pallate.
rightPalllate.PNG
In the below code, we have created a function “Search” which search the staff record:
searchStaffController.js
({
Search: function(component, event, helper) {

component.set("v.isNew",false);
var searchKeyFld = component.find("searchId");
var srcValue = searchKeyFld.get("v.value");
if (srcValue == '' || srcValue == null) {
// display error message if input value is blank or null
searchKeyFld.set("v.errors", [{
message: "Enter Search Keyword."
}]);
} else {
searchKeyFld.set("v.errors", null);
// call helper method
helper.SearchHelper(component, event);
}
},
navigateToStaff : function(component, event, helper) { 

component.set("v.isNew",false);
component.set("v.isView",true);
component.set("v.objId",event.target.id); 
component.set("v.headerText","My Staff");

// Get the application event by using the
// e.. syntax
var appEvent = $A.get("e.c:StaffViewCompEvent");
appEvent.setParams({"recordId" : event.target.id});
appEvent.fire();

} ,
createNew : function(component){ 
component.set("v.headerText","New Staff");
component.set("v.isNew",true);
component.set("v.isView",false);

},
searchShow : function(component){ 
component.set("v.headerText","Search Staff");
component.set("v.isNew",false);
component.set("v.isView",false);

}

})
searchStaffHelper.js
({
 SearchHelper: function(component, event) {
 var action = component.get("c.fetchStaff");
 action.setParams({
 'searchKeyWord': component.get("v.searchKeyword")
 });
 action.setCallback(this, function(response) {
 var state = response.getState();
 if (state === "SUCCESS") {
 var storeResponse = response.getReturnValue();
 // if storeResponse size is 0 ,display no record found message on screen.
 if (storeResponse.length == 0) {
 component.set("v.infoMessage", true);
 } else {
 component.set("v.infoMessage", false);
 }
 // set numberOfRecord attribute value with length of return value from server
 component.set("v.numberOfRecord", storeResponse.length);
 // set searchResult list with return value from server.
 component.set("v.searchResult", storeResponse);
 }
 
 });
 $A.enqueueAction(action);
 
 },
})

 

Event: 

In the Lightning framework, events are fired from JavaScript controller actions. Events can contain attributes that can be set before the event is fired and read when the event is handled. This event named “StaffViewCompEvent” helps to navigate to the staff page when clicked on any staff in the results.

staffViewCompEvent.evt

 
<aura:event type="APPLICATION" description="Event template" >
 <aura:attribute name="recordId" type="Id"/>
</aura:event>

Link: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/events_component_create.htm

Lightning Tab

Tab helps to display the component to create a record using component. In order to create a lightning tab. Please follow the below instruction:

The component must include below markup:- (we have already done this)

Here is the link to create lightning tab step by step:

https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/aura_add_cmp_lex.htm

NOTE: We need to choose the lightning component based on the name which we have created in this blog.

Lightning App

Let’s first create an Lightning app to store the tabs which we will use to plug lighting component:

In the Lightning experience, click on setup > Apps > App Manager > Click on New Lighting App. On the page “Select Items” , we need to select our created lightning component created in this blog.

In this blog, we have described the lighting components and code to search and display the data. The component code also contains the reference of other components which we will discuss in our next series like viewing and editing the records etc.

To be continued…

 

How to deploy apex code using ANT ?

A developer want to push the components/metadata like Objects, Fields , Validation Rules, Workflows and Apex Code etc. We can use Change Set, Force.com IDE and ANT Migration tool. However there are some extra features provided in this ANT migration tool. In this blog, we are gonna demonstrate the most powerful tool ANT mostly used for our major deployments.

ANT migration tool (based on JAVA), is used to deploy the Metadata from one organization to other organization or we can use it to retrieve the metadata from one organization and then make some changes locally and then deploy that metadata again to the same organization.

Features of ANT Migration Tool

  • The main advantage of this tool is, that it gets the metadata in form of XML files from your server and downloads it locally on your computer. Thus you can make changes in those XML files locally and again deploy the changes to any server instance, any target org that you want.
  • It allows you to deploy the same metadata any number of times to any of your server, as you have downloaded the metadata in form of XML files, you can deploy them again and again.
    • Change set does not allow you to delete any metadata component from target org. But using ANT migration tool you can delete the components from target org. This is done using destructiveChanges.xml file.
  • Some components are not supported to be migrated using change sets but you can migrate them using ANT migration tool.
  • It can also be run from command prompt using some specific commands for calling APIs.
  • You can also automate your migration process leveraging the capabilities of command prompt .bat files and XML structure of source files.

Here are the few steps that we need to take in order to push our changes:-

Step 1 (Install ANT Migration Tool)

Please click here to install prerequisites and ANT Migration Tool. Save the .zip file locally, and extract the contents to the directory of your choice. If you are using Windows, please use a folder in C:\ for example ‘C:\Tools\apache-ant-1.10.3’ to avoid windows limitation for directory length.

In order to start deployment, we need to download the .zip file which contains set of configuration files. This helps developers to configure username and password, getting metadata and build scripts to run on command prompt. 

( The above download link doesn’t require authentication to Salesforce. If you’re logged in to Salesforce, we recommend you log out before accessing the link in your browser. )

Please extract the salesforce_ant_42.0.zip to ‘C:\Tools\salesforce_ant_41.0’. Will discuss about the each file later in this blog. Here is the screenshot of sample files.

ant

Step 2 (Setup Environment Variables)

You need to set the environment path variables which will help you to access ant tools from any folder through the command line.

Go to Control Panel > System > Edit the System Environment Variables

env

  • Create a ANT_HOME and JAVA_HOME variables under ‘System Variables’
  • Create an ANT_HOME environment variable and set the value to where you have installed Ant. e.g. C:\Tools\apache-ant-1.10.3
  • Create JAVA_HOME environment variable and set the value to the location of your JDK. e.g. C:\Program Files\Java\jdk1.8.0_171
  • Add C:\Tools\apache-ant-1.10.3\bin to the list of existing PATH variablepath

Step 3 (Test Installation)

Once you done with the above steps now it’s time to check if everything is all set to go.

  • Open command prompt or terminal and type ant or ant –version and press enter

cmd

To get started  first, let’s understand the important files available inside the salesforce -ant folder (C:\Tools\salesforce_ant_41.0\sample):

build.properties

We provide the login credentials in build.properties. Open build.properties and enter your Dev Org credentials. Don’t forget to append the security token to the password.

build

build.xml

Here we provide the scripts to retrive or deploy or any other possible operation. We use tags like “retrieveCode” or “deployCode” in build.xml. These tags are also called targets. We can run these targets one by one and complete the task in sequential manner as we want. build.properties is also referred in build.xml for required credential and login urls.

  • Search for “retrieveCode” in build.xml. You will see unpackaged=”codepkg/package.xml”

retrieveCode

  • Open package.xml from ‘codepkg/package.xml’, and modify package.xml. You will enter the class and trigger you like to retrieve from Salesforce in package.xml

package

This is the last xml file that we need. We have to mention the API name of components that we want to retrieve from source org. And the same xml can be used while deploying those components to target org.

Step 4 (Retrieve and Deploy Code)

deployCode
You may navigate to Salesforce > Deployment Status to verify deployment
deploymnet
Deployment without running Test Class
In this case, we are not running the tests which can be configured in build.xml by setting testLevel=”NoTestRun”
notestrun
Deployment with running Specified Tests
We can run specific test class by setting testLevel=”RunSpecifiedTests” with adding below runTest child tag in the above script.
TestClass1
TestClass2
runspecifictests

References

 

For more details about build.xml scripts, please click on following link

How to delete a class or trigger, please click on the following link

To rename a component, you must delete the component, and then recreate it with a new name. It cannot be done directly because we don’t maintain the ID’s of components in the case of ANT. Please click on the following link for more information

 

SOQL Query Analysis using Query Plan tool and Optimization using filters & Custom Indexes.

Why SOQL Optimization is Needed ?

SOQL is a tool that lets you access records in your Salesforce database. When you don’t write good SOQL queries you’re going to hit the governor limit of non selective query. There is a very common issue that most of us have came across when there are more than 100k records in a given table. For e.g.  If we cross the threshold of 100k records, we might start to see some “non-selective query” type errors mentioned below:

Error Non Selective

 

SOQL query should always be selective meaning it must contain at least one query filter on an indexed field and that filter in turn reduces the resulting number of rows below a Salesforce-determined threshold*.

Analyze SOQL queries using Query Plan tool 

When it comes to optimize the SOQL, we first need to analyze the SOQL to identfiy the weak areas of SOQL and it’s running performance. The Query Plan tool shows the cost of Salesforce executing a given SOQL query given the database statistics known at that time.

Enabling Query Plan

Salesforce doesn’t have the Query Plan feature enabled by default. To enable it, open the Developer Console –> Help –> Preferences and then check “Enable Query Plan”.

Using Query Plan

After the Query Plan is enabled, open the Query Editor tab at the bottom, enter a SOQL query, and click the Query Plan button. This will open a modal showing the cost of the SOQL query along with helpful tips.

QueryPlan

  • Cardinality – The estimated number of records that will be returned by the query.
  • Fields – The indexed field(s) used by the Query Optimizer. If the leading operation type is Index, the fields value is Index. Otherwise, the fields value is null.
  • Leading Operation Type – The primary operation type that Salesforce will use to optimize the query.
    • Index – The query will use an index on the queried object.
    • Sharing – The query will use an index based on the sharing rules associated with the user who is executing the query. If there are sharing rules that limit which records that user can access, Salesforce can use those rules to optimize the query.
    • TableScan – The query will scan all records for the queried object.
    • Other – The query will use optimizations internal to Salesforce.
  • Cost – The cost of the query compared to the Force.com Query Optimizer’s selectivity threshold. Values above 1 mean that the query won’t be selective.

In above example, we query all Accounts with non-selective filter which is “Is Deleted”, the cost is high.

  • SObject Cardinality – The approximate record count for the queried object.
Salesforce Query Plan How To
Optimize SOQL using Filters and Custom Index : 
  • We must only select the fields which are needed but not all fields.
  • We should try to use the limit operator to reduce how many records are returned.
  • We must use indexed fields- selective filters

Here are the three examples which shows how the initial non-selective query is being optimized with adding more filters to it.

// Non- Selective Query- This will return everything from the table 

List<Contact> = [SELECT Id, Name, Email, OwnerId from Contact ];

// Better Query than above one, we’ve got a filter but it is not on an indexed field

List<Contact> = [SELECT Id, Name, Email, OwnerId from Contact Where Status = ‘Active’];

// Even better since Owner is one of the standard indexed fields. The performance of the SOQL //query improves when two or more filters used in the WHERE clause meet the mentioned //conditions.

List<Contact> = [SELECT Id, Name, Email, OwnerId from Contact Where Status = ‘Active’ and OwnerId IN (‘005d0000001acWo’,’005d0000001mnTo’) ];

Developer must use Indexed fields to improve the performance of SOQL query.

Custom Index and Considerations 

Salesforce leverages indexes heavily to optimize query performance whenever possible. An index is a separate data structure that stores field values in such a way that it’s fast to search on them to identify the rows we’d like returned. The general concept is the same as a book’s index.

What fields are pre- indexed?

  • Object Ids
  • Object Name – Auto Number or Text Field.
  • Custom Relationsips – Master Details and Lookups.
  • External Ids
  • Unique Fields
  • Owner Field

Use an index in the where clause whenever possible. However, this doesn’t guarantee that it will be used. Salesforce has various rules around when an index will be used or not based on its selectivity.

  • An indexed field will not be used under the following conditions:
    • Not In (…)

e.g. Status__c Not IN (‘Active’) – Even if Status__c is indexed field, it won’t be considered as indexed field and might occur non-selective error. 

    • Like with wildcards “%Field%”
    • !=
    • Excludes for picklist values
    • Not Like
    • Comparison Operators Paired With Text Fields. Text_Field <, >, <=, >

Not sure if a field is indexed or not ? Open an object’s definition page and notice that there’s an “Indexed” column. If it’s checked, it’s indexed.

Indexed

How to get field Indexed which is not indexed ?

Please submit a case with Salesforce Support.

For more information custom index:-

 

Salesforce Apex Code Repository

Salesforce provides couple of developer related objects which are very useful when a developer wants to fetch the metadata information of apex class, components, pages, triggers, code coverage using apex code. There are lot of scenarios where we can utilize these objects :-

  1. To search any referenced fields and objects inside apex classes,pages & triggers.
  2. To Create an Apex Class, Apex Triggers, Apex Pages via API.
  3. To find out the package related classes or triggers.
  4. To check the number of test classes and running test results.
  5. To check the coverage of classes and triggers.

We have the following objects which represent Apex Code Repository:-

  1. ApexClass
  2. ApexComponent
  3. ApexPage
  4. ApexTrigger
  5. ApexTestResult
  6. ApexCodeCoverage
  7. ApexCodeCoverageAggregate

ApexClass

This object represents apex class.

For e.g. A Developer wants to show the list of classes related to a package called “APTTUS” , we can use a field NameSpacePrefix to filter out the classes related to package using below SOQL:

Select Name From ApexClass Where NameSpacePrefix = 'APTTUS'         

For more information about ApexClass object.

ApexTrigger

This object represents Apex Triggers.

For e.g. A Developer wants to show the list of Apex Triggers on the Account object. We can use a field called TableEnumOrId with passing the Object Name and below SOQL will return all the triggers written on Account object.

Select Name From ApexTrigger Where TableEnumOrId = 'Account'         

For more information about ApexTrigger object.

ApexPage

This object represents a Visualforce Page.

For e.g. A Developer wants to show the list of Visualforce Pages defined with the standardController attribute on the <apex:page> tag

Select Name From ApexPage Where ControllerType = 'Standard'   

For more information about ApexPage object.

ApexTestResult

This object represents the Test Results produced by apex tests. Each test method execution is represented by a single ApexTestResult record.

For e.g. A Developer wants to show the list of apex test results ran for an apex class “XYZ”. Here XYZ is the ID of Apex Class. Below SOQL will return the test results for the same:

Select Name From ApexTestResult Where ApexClassId = 'XYZ'   

For more information about ApexTestResult object.

ApexCodeCoverage

This object represents code coverage test results for an Apex class or trigger. This object is accessible via Tooling API only. This object is specifically used to design a statistic report for any apex class or trigger.

This object needs a REST Call to access the data stored into this object. Below is the sample code to get the data using REST call:


HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint(wrapObj.instance_url+'/services/data/v39.0/tooling/query/?q='+SELECT+id,ApexTestClass.Name,TestMethodName,NumLinesCovered,NumLinesUncovered,ApexClassorTrigger.Name,ApexClassorTrigger.Type,Coverage+from+ApexCodeCoverage+where+ApexClassorTriggerId);
req.setHeader('Authorization', 'OAuth '+wrapObj.access_token);
req.setTimeout(120000);
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug('***Response Body****'+ res.getBody());
return res.getBody();

For more information about ApexCodeCoverage object.

ApexCodeCoverageAggregate

This object represents aggregate code coverage for a  Class or Trigger. For E.g. :-  We want to see the coverage for a specific class covered by all test methods, so we can use this object in our REST call. 

In Summary, Salesforce provides the flexibility to play around with the metadata of developer objects in Apex Code.

Salesforce Tweaks using Chrome Plugins

Admin/Developers spend lot of time in opening, searching, navigating, analyzing, assigning permissions on setup or non setup items using Salesforce standard functionality.

There are couple of plugins for developers-

Salesforce advanced Code searcher

1. Search for any code inside Apex Class, Visualforce page, Triggers etc.

2. Find and open any Class, Visualforce, Triggers, Components, Templates.

3. Extract Code Coverage. 

To speed up the above mentioned activities, there is a plugin called:

By using the advanced quick find you can get your code few clicks shorter. Also, you can search any string your code Also, you can search any string your code

In addition to the above you can use this extension to jump to classes / pages / triggers from the advanced quick find section on the left hand side.

SF Quick Metadata Lookup

Find any metadata in your org. 

To download the above plugin:

 

Salesforce API FieldNames

Shows the API field names on detail pages.

To download the above plugin:

SOQL Extractor and Analyzer for Salesforce

Extract SOQL queries with their execution counts from Debug Logs of Salesforce. Helps Developer to analyze the ‘Too Many SOQLs’ error.

To download the above plugin: