Apex Invocable Actions

                       Let us discuss here how to use apex action. Action encapsulate a piece of logic that allows a user to perform some work, such as sending the email. Use actions to add more functionality to your applications. Choose from standard actions, such as posting to Chatter or sending email, or create actions based on your company’s needs. To run the apex invocable actions you need to use  InvocableMethod Annotation. Invocable methods are called with the REST API and used to invoke a single Apex method. Invocable methods have dynamic input and output values and support describe calls. The following code sample shows an invocable method with primitive data types. Represents a standard or custom invocable action.

public class AccountQueryAction {
    @InvocableMethod(label='Get Account Names' description='Returns the list of account names corresponding to the specified account IDs.')
    public static List<String> getAccountNames(List<ID> ids) {
        List<String> accountNames = new List<String>();
        List<Account> accounts = [SELECT Name FROM Account WHERE Id in :ids];
        for (Account account : accounts) {
        return accountNames;

Calling as an Apex Actions

Now you can able to call the apex class from the apex action using the rest API resource.use the following rest API resource.

Now login into the workbench and run the following rest API using the rest utils. This example invokes the Apex action called AccountQueryAction , which takes a list of IDs and returns a list of associated account names. The top-level key name in the JSON request body must be inputted.

Note The resource is the name of the Apex class, not the Apex method. 

here is the request body for the post method


After executing the rest API you can able to see the response as shown below.

Quick Notes 

  1. Describe and invoke for an Apex action respect the profile access for the Apex class. If you don’t have access, an error is issued.
  2. If you add an Apex action to a flow and then remove the @InvocableMethod annotation from the Apex class, you get a run-time error in the flow.
  3. If an Apex action is used in a flow, packageable components that reference these elements aren’t automatically included in the package.
  4. An Apex invocable action can be declared public or global in a managed package. However, that action doesn’t appear in the Cloud Flow Designer’s list of available actions while building or editing a flow. These invocable actions can still be referred to by flows within the same managed package. Global Apex invocable actions in a managed package can be used in flows outside the managed package, anywhere in the organization, and appear in the Cloud Flow Designer’s list of available actions to add to a flow.

Refer this links for more information on input and output variable support






Lightning Component Quick Actions


In this blog, I am going to explain how to custom actions to customize lightning and  Salesforce1 experiences with both global actions and quick actions. Global actions are not associated with any object means you can insert data that is not going to establish any relations other record and Object-specific actions are associated with the object so it allows creating records that have automatic relationships to other records, make updates to specific records. To available Lightning component as actions, you need to implement either the force: LightningQuickAction or force: LightningQuickActionWithoutHeader interfaces.Add the force:hasRecordId interface to a Lightning component to enable the component to be assigned the ID of the current record. When we implement the force:lightningQuickAction interface display in a panel with standard action controls, such as a Cancel button. If instead, you want complete control over the user interface, use the force: lightningQuickActionWithoutHeader interface. Components that implement the force:lightningQuickActionWithoutHeader display in a panel without additional controls and are expected to provide a complete user interface for the action.

Object-Specific Actions
What we are going to do it here, we will create a quick action that is going to create a quote from the opportunity. Create an apex class as shown below and the apex class is used to communicate to server-side actions to save the Quote.

public class QuickQuote {
    public static boolean saveQuote(Quote newQuote, Id oppId) {
        newQuote.OpportunityId = oppId;
            insert newQuote ; 
            return true ;
        }catch(Exception e){
            throw new AuraHandledException(e.getMessage());
            return false ;

Go to developer console and create a new lightning component name ” Quick Quote” with below code

<aura:component controller="QuickQuote"
    <aura:attribute name="recordId" type="String" />
    <aura:attribute name="newQuote" type="Quote"
                    default="{ 'sobjectType': 'Quote','Name':'Default Quote' , 
                             'ExpirationDate':'2017-10-30','Email':'test@email.com' ,'Phone':'' ,'Discount':'19' , 'BillingName':'Teest' }" /> 
    <div class="slds-page-header" role="banner">
        <h1 class="slds-page-header__title slds-m-right--small
                   slds-truncate slds-align-left">Create New Quote</h1>
    <lightning:input aura:id="quoteName" 
                     name="Quote Name" 
                     label="Quote Name" 
    <ui:inputDate aura:id="quoteDate" displayDatePicker="true"
                  label="Expiration Date" 
    <lightning:input aura:id="quoteEmail"
                     name="Email Date" 
    <lightning:input aura:id="quotePhone" 
                     name="Phone Date" 
    <lightning:input aura:id="quoteDiscount" 
    <lightning:button label="Create Quote" onclick="{!c.createQuote}"
    <lightning:button label="Cancel" onclick="{!c.handleCancel}" class="slds-m-top--medium" />

Here is Lightning component controller code.

    createQuote: function(component, event, helper) {
        var saveAction = component.get("c.saveQuote");
            newQuote: component.get("v.newQuote"),
            oppId: component.get("v.recordId")  
        saveAction.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS") {
                var resultsToast = $A.get("e.force:showToast");
                    "title": "Quote",
                    "message": "Quote Creation is Success."
            else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + 
                } else {
                    console.log("Unknown error");
        console.log('En Quier action ');
    handleCancel: function(component, event, helper) {

The createQuote action handler method will do the following action

  • Invoke server action to save the quote by calling component.get(“c.saveQuote”) from the apex class .
  • Defines a callback function to handle the server response.
  • Enqueues the server action by calling” $A.enqueueAction(saveAction)
  • handleCancel Closes the action panel by firing the force:closeQuickAction event.
  • Displays a “toast” message that the Quote was created by firing the force:showToast event.

Go to Opportunity and create an action as shown below.

Add it to the opportunity  Salesforce1 and Lightning Experience Actions section on the page layouts to create quote by using actions.


Global Actions

Now we are going to create global actions that allow users to create the new user from the global action.
create a new apex class “CreateNewUser” with the below code.

public class CreateNewUser {
    public static void insertNewUser(User userInsert ){
            User temp = userInsert ; 
            Database.DMLOptions dmo = new Database.DMLOptions();
            dmo.EmailHeader.triggerUserEmail = false;
            String profileId =[Select id from Profile where name = 'Chatter Free User' Limit 1] .Id;
            temp.ProfileId = ProfileId;
            temp.TimeZoneSidKey = 'America/Los_Angeles';
            temp.LanguageLocaleKey = 'en_US';
            temp.EmailEncodingKey ='UTF-8';
            temp.LocaleSidKey = 'en_US';
            insert temp ;  
        }catch(Exception e){
            throw new AuraHandledException(e.getMessage());

Go to developer console and create a new lightning component “CreateNewUser” with below code.

<aura:component controller="CreateNewUser" implements="force:lightningQuickActionWithoutHeader">
    <aura:attribute name="newUser" type="User"  default="{ 'sobjectType': 'User',
                                                         'FirstName':'' , 
                                                         'Email':'' ,
                                                         'Username':'' ,
                                                         }" />
    <ui:inputtext label="First Name" value="{!v.newUser.FirstName}"/>
    <ui:inputtext label="Last Name" value="{!v.newUser.LastName}"/>
    <ui:inputemail label="Email" value="{!v.newUser.Email}"/>
    <ui:inputemail label="User Name" value="{!v.newUser.Username}"/>
    <ui:inputemail label="Alias" value="{!v.newUser.Alias}"/>
    <lightning:button label="Save " onclick="{!c.handleSave}"
                      variant="brand" class="slds-button slds-button_brand slds-col_bump-left"/>

Here is the component controller.

    handleSave: function(component, event, helper) {
        var newUserInsert = component.get("c.insertNewUser");
            "userInsert": component.get("v.newUser")
        newUserInsert.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS") {
                // Prepare a toast UI message
                var resultsToast = $A.get("e.force:showToast");
                    "title": "Record is  Created  !",
                    "message": response
                // Update the UI: close panel, show toast, refresh account page
            else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + 
                } else {
                    console.log("Unknown error");
                else {
                    console.log('Unknown problem, response state: ' + state);
        // Send the request to create the new contact

Go to Global action from the setup menu and create a new global action as shown below.

Go to publisher layout from the setup menu and add the lightning component create to the layout as shown below.

You can access global action from salesforce global header.








Visualforce Page Actions


In this blog post, I am going to explain how to set up global actions and object-specific actions by using visualforce page.The global action which we are going to see in this blog is to send the message to slack channel and object specific action is to take the case ownership from the assigned queues.

Global Actions:-

As we are going to going to post the message to slack by using the global action, go and create a Slack app and get the slack token. Please refer this link

visualforce page is here below

<apex:page controller="GlobalSlackActions" lightningStylesheets="true" sidebar="false" showQuickActionVfHeader="false" docType="html-5.0">
    <apex:slds />
    <div class="slds-scope">
        <apex:form >
            <apex:actionFunction action="{!postMessagetoSlack}" name="postSlackMessage" rerender="out"
            <apex:outputPanel id="out">
                <div class="slds-form--compound slds-m-top--xxx-small">
                    <div class="slds-form-element">
                        <div class="slds-form-element__row slds-align_absolute-center">
                            <label class="slds-form-element__label" for="sample1">#Slack Channel</label>
                            <div class="slds-form-element__control slds-picklist">
                                <apex:selectList id="countries" value="{!slackChannel}" size="1" required="true" styleClass="slds-input">
                                    <apex:selectOptions value="{!ListOfSlackChannels}"/>
                    <div class="slds-form-element">
                        <div class="slds-form-element__row slds-align_absolute-center ">
                            <label class="slds-form-element__label " for="sample2"> Name </label>
                            <div class="slds-form-element__control slds-picklist">
                                <apex:inputTextArea value="{!slackTextMessge}"  id="sample1" styleClass="slds-input"/>
            <div class="slds-form-element slds-align_absolute-center">
                <button  onclick="postSlackMessage();" styleClass="slds-button slds-button_neutral">Post to Slack </button>
                <button  onclick="closeAction();" styleClass="slds-button slds-button_neutral">Close  </button>


And the controller is here.

public class GlobalSlackActions {
    public String slackChannel {get;set;}
    public List<SelectOption> channelNameOptions{get;set;}
    public String slackTextMessge {get;set;}
    public String slackToken {get;set;}
    public GlobalSlackActions(){
        slackToken ='xoxp-167092741267-167199659508-179751455458-6fd12a391bd432b735b4efcb1313193f';
    public List<SelectOption> getListOfSlackChannels () {
        String slackEndpoint = 'https://slack.com/api/channels.list?token='+slackToken;
        HttpResponse res = buildHttp(slackEndpoint);
        if(res.getStatusCode() ==200){
            JSON2Apex cls =  (JSON2Apex)parse(res.getBody());
            list<Channels> c =cls.channels ; 
            List<SelectOption> options = new List<SelectOption>();
            for(Channels cName :c){
                options.add(new SelectOption(cName.name,cName.name));
            return options ; 
            return null ;
    public class JSON2Apex {
        public Boolean ok;
        public List<Channels> channels{get;set;}
    public class Channels {
        public String id;
        public String name{get;set;}
        public Boolean is_channel;
        public Integer created;
        public String creator;
        public Boolean is_archived;
        public Boolean is_general;
        public Integer unlinked;
        public String name_normalized;
        public Boolean is_shared;
        public Boolean is_org_shared;
        public Boolean is_member;
        public Boolean is_private;
        public Boolean is_mpim;
        public List<String> members;
        public Integer num_members;
    public static JSON2Apex parse(String json) {
        return (JSON2Apex) System.JSON.deserialize(json, JSON2Apex.class);
    public PageReference postMessagetoSlack () {
        String slackEndpoint = 'https://slack.com/api/chat.postMessage?token='+slackToken+'&channel='+slackChannel+'&text='+slackTextMessge+'&pretty=1';
        return null ;
    public HttpResponse buildHttp(String url){
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse(); 
        res = h.send(req);
        return res ;

Go to set up, find global actions and create a new one as shown below.

Add to the publisher layout as shown below.

After saving the publishers layout you can able to see the quick actions as shown below.

Object Specific actions

Now I am going to walk thru how to create the object specific action.To associate an action to object you need to user standardController attribute of the object. Here we are going to create a Case Quick actions which are allowing the user to take the ownership of the case from case queue.

Here is the visual force page

<apex:page standardController="Case" extensions="CaseTakeOwnership" showQuickActionVfHeader="false">
    <apex:form id="demo">
        <apex:actionFunction action="{!takeOwnership}" name="takeOwner" reRender="demo" oncomplete="refreshFeed();"/>
        <div style="align:center">
            <button  onclick="takeOwner();" class="sucessBtn">Take Ownership</button> <br/><br/><br/><br/>
            <button onclick="closeAction();" class="closebtn">Cancel</button>

The controller is here below.

public class CaseTakeOwnership {
    public Case careRecord {get; set;}
    public CaseTakeOwnership(ApexPages.StandardController controller) {
        careRecord =(Case)controller.getRecord();
    public PageReference takeOwnership() {
        try {
            careRecord.OwnerId = UserInfo.getUserId();
            update careRecord;
        } catch(Exception ex){
        return null ;

Both in global action and Object actions, I set showQuickActionVfHeader to false. So that we will not able to see the Standard Submit and Cancel Global action header.

Now go to Case Object buttons and links and create a new action as shown below

Add the object to quick action, salesforce 1 and lightning action on page layout based on whether you wanted to show on salesforce class or salesforce 1 as shown below.


Publisher Events

Refresh feed (desktop) 

Sfdc.canvas.publisher.publish({ name: 'publisher.refresh',
 payload: {feed:true}

Submit hook (Salesforce1)

Sfdc.canvas.publisher.subscribe({name: "publisher.showPanel",
 onData:function(e) {
 "publisher.setValidForSubmit", payload:"true"});
Sfdc.canvas.publisher.subscribe({ name: "publisher.post",
 onData: function(e) {
 alert("call some remote action here");
 Sfdc.canvas.publisher.publish({ name: "publisher.close",
 payload:{ refresh:"true" }});

Close publisher event

        Sfdc.canvas.publisher.publish({name: "publisher.close", payload:{ refresh:"true" , successMessage: 'Cancel!'}});  

Activate publish button 

    name: "publisher.setValidForSubmit", 
Clear Panel State
             { name : "publisher.clearPanelState", onData:function(e) { alert('Fire ClearPanelState'); }}

Show Panel State 

             { name : "publisher.showPanel", onData:function(e) { alert('Fire ShowPanel'); }}
Success State 
            Sfdc.canvas.publisher.publish({ name : "publisher.success", payload : { feed:true }});


Redirect (Salesforce1)

sforce.one.navigateToFeed(subjectId, type)
sforce.one.navigateToRelatedList(relatedListId, parentRecordId)
sforce.one.navigateToList(listViewId, listViewName, scope)
sforce.one.createRecord(entityName, recordTypeId)


Salesforce Quick Actions


In this blog post, I am going to explain salesforce action. Actions enable users to do more in Salesforce and in Salesforce1, the Lightning experience depends on the chatter settings. You can create an action and add them to the Chatter publisher on the home page, on the Chatter tab, in Chatter groups, and on record detail pages.  In Salesforce Classic, actions appear in the Chatter publisher. In Lightning Experience, actions appear in different areas of the user interface, depending on the action’s type. In Salesforce1, actions appear in the action bar, its associated action menu, and as list-item actions.

Action Categories

Actions have the different type of categories

Standard actions

Standard actions are actions that are included automatically when Chatter is enabled: Post, File, Link, Poll, and, in organizations that use work.com, Thanks, Announcements are default actions.

Default actions

Default actions are Salesforce predefined actions to get you and your users started using actions in your organization. Add default actions to publisher layouts to make them available to your users in the full Salesforce site and the action bar in Salesforce1.

Mobile smart actions

Mobile smart actions are a set of preconfigured actions, just like default actions, and are supported on the same list of objects. However, they appear in pre-Winter ’14 organizations and are displayed only in Salesforce1.Mobile smart actions are populated with all your organization’s required fields on the relevant object, regardless of how many fields there are.Mobile smart actions don’t appear in the full Salesforce site, regardless of which page layouts you add them to; they appear only to users in Salesforce1.

Custom Actions

Custom actions are actions that you create and customize yourself, such as Create a Record, Send Email, or Log a Call actions. They can also invoke Lightning components, Visualforce pages, or canvas apps with functionality that you define.

Productivity Actions

Productivity actions are predefined by Salesforce and are attached to a limited set of objects. You can’t edit or delete productivity actions.The actions include Send Email, Log a Call, Map, View Website, and Read News.

Type of Actions

Within the categories of actions, you can have different types of actions, depending on their function.

  • Create actions let users create records.
  • Send email actions available only on cases, give users access to a simplified version of the Case Feed Email action on Salesforce1
  • Log call actions let users record the details of phone calls or other customer interactions.
  • Question actions enable users to ask and search for questions about the records that they’re working with.
  • Update actions users make changes to a record.

Steps to define Quick action

Now it’s time to define the quick action. defining quick action contains the below steps.

  1. Enable Actions in the Chatter Publisher
  2. Enable feed tracking for the objects for which you want to make actions available.
  3.  Enable actions in the publisher if you want to see both standard actions and non-standard actions in the Chatter publisher.
  4.  Optionally, enable feed updates for related records to display feed items on a record detail page when related records are created.
  5.  Create object-specific actions or global actions.
  6.  Customize the action layout with the fields that you want users to see when they use the action.
  7.  Add the actions to page layouts or global publisher layouts.

1. Global Actions 

Let’s create a global action that allows users to create an order from chatter.Global actions let users do tasks such as creating records or recording call details directly from the publisher on the Home tab, the Chatter tab, the action bar on the Salesforce1 feed, and Chatter groups.  You can also add global create actions to record detail pages.  Global actions enable users to create object records, but the new record has no relationship with other records.

  1. From Setup, enter Actions in the Quick Find box, then select Global Actions.
  2. Click New Action.
  3. For Action Type, leave Create a Record selected.
  4. For Target Object, select Order.
  5. Enter Label as “New Order”
  6. On Success Message Enter “Order is successfully created “

After click on Save page will redirect to action layout which allows users to customize action layouts as shown below. action layouts are similar to page layout where you can add fields to layouts. add the fields as shown below and click on save.

Predefined field values

Predefined field values will populate the values with predefined values on the action. Setting up predefined values for certain fields on actions can increase your mobile users.  Go to global action New Order which we created. you can see related predefined values.In the Predefined Field Values related list, click New and add fields as shown below.

Adding to Global Publisher Layout

Global publisher layouts determine which actions appear in the publisher in various pages throughout Salesforce, including the Home tab, Chatter tab, and Chatter group detail pages in the full site, as well as the action bar and action menu in Salesforce1. Global publisher layouts can include only global actions. Go to publisher layout edit and add the global action as shown below

Now you can able to see global action on chatter feed as shown below


2. Object-Specific Quick Actions

Object-specific actions let users quickly create or update records, log calls, send emails, and more, in the context of a particular object.You create object-specific actions in the context of the object. object-specific create actions create records that are automatically associated with related records. For example, you add an object-specific action on the Account object that creates contacts. If a user creates a contact with that action on the detail page for the Acme account, that new contact is automatically associated with Acme.Object-specific update actions make it easy for users to edit records. You can define the fields that are available for update.Let’s assume that you wanted to create a Competitor from the account feed. We are going to create a quick action on the account.

Create an Object-Specific Action

Go to Account Object -> go to Buttons, Links, and Actions and click New Action and create an Action as shown below

Add an Action to Account Page Layout

After creating an action you need to add to the page layout to appear in the feed. Go to Account Page and add the action as shown below.Finally, you can see the Action on feed as shown below.