trailhead

Implement Object-Specific Actions with Visualforce Pages

Learning Objectives

After completing this unit, you’ll be able to:
  • Describe the two most significant requirements of an object action, as compared to a global action.
  • Implement a Salesforce app object action using a Visualforce page.
  • Style a page using the Salesforce Lightning Design System to improve usability for a mobile user interface.

Implement Object-Specific Actions with Visualforce Pages

When you create an object-specific action using a Visualforce page, that page is executed with the current object. In other words, a specific record ID is associated with the Visualforce page.

Visualforce pages used to implement object-specific actions must use the standard controller for that object. The standard controller automatically loads the record for the record ID.

Generally, when the action completes, users are redirected to a page related to the originating record.

Create a Visualforce Page for the Object-Specific Action

Object-specific actions open a Visualforce page, which can in turn invoke more pages. You must define the first page before you can create the action that launches it.

Let’s create an object-specific action that provides a simple two-button widget to close an opportunity as either won or lost.

  1. Open the Developer Console and click File | New | Visualforce Page. Enter CloseOpportunity for the page name.
  2. In the editor, replace any markup with the following.
    <apex:page docType="html-5.0" standardController="Opportunity" title="Close Opportunity">
    
        <script src='/canvas/sdk/js/publisher.js'></script>
    
        <apex:remoteObjects>
            <apex:remoteObjectModel name="Opportunity" fields="Id,Name"/>
        </apex:remoteObjects>
        
        <div class="mypage">
            <button onclick="closeOpportunity('Closed Won')">Won</button>
            <button onclick="closeOpportunity('Closed Lost')">Lost</button>
        </div>
        
        <script>
            var opportunityId = "{!Opportunity.Id}";
    
            function closeOpportunity(stageName) {
                var opportunity = new SObjectModel.Opportunity();
                opportunity.update([opportunityId], {StageName: stageName}, function(error, records) {
                    if (error) {
                        alert(error.message);
                    } else {
                        Sfdc.canvas.publisher.publish({ name: "publisher.close", payload: {refresh:"true"}});
                    }
                });
        }
        </script>
        
    </apex:page>

This page is simple, but it illustrates several details about writing your own object actions. First, the page uses the standard controller for opportunities, as required. But notice something interesting: It only uses the standard controller to load the details for the opportunity. Once again, the page uses Remote Objects, this time to update an existing record. So the page loads data using the standard controller, but updates it with Remote Objects, combining two different data access methods on the same page.

Beyond the Basics

Why not use the standard controller to update the record, too? Put simply, Remote Objects fits better with the page interaction model used by the Salesforce app. You can use standard Visualforce in the Salesforce app, but to optimize your pages for the mobile environment, you’re better off using Visualforce tools like Remote Objects or JavaScript remoting. They connect better with JavaScript-based Salesforce app features like sforce.one and the Publisher SDK. They also perform fewer requests with smaller data payloads, which can improve performance quite a bit for mobile devices.

Finally, we handle a successful update of the opportunity using a callback function similar to the one defined in the Quick Account page. Except this time, instead of using a sforce.one navigation function, we use the Publisher SDK to close the publisher and refresh the opportunity we were on.

Create an Object-Specific Action with the Visualforce Page

Object-specific actions are associated with a particular object, so they’re created on the object in Setup.

To create an action for Opportunities with the CloseOpportunity page, do the following.

  1. From Setup, enter Visualforce Pages in the Quick Find box, then select Visualforce Pages, and then enable the page for mobile apps.
    You learned how to enable a page for mobile apps in a previous unit.
  2. Define the action for the object.
    1. From Setup, enter Object Manager in the Quick Find box, then click Object Manager | Opportunity | Buttons, Links, and Actions.
    2. Click New Action.
    3. In the Action Type drop-down list, select Custom Visualforce.
    4. In the Visualforce Page drop-down list, select CloseOpportunity.
    5. In the Label field, enter Close Opportunity.
      The other default values are fine.
      Create an object-specific action
    6. Click Save.
  3. Add the action to the publisher layout.
    1. From Setup, enter Object Manager in the Quick Find box, then click Object Manager | Opportunity | Page Layouts.
    2. Select Edit from the drop-down to the right of Opportunity Layout.
    3. In the Salesforce Mobile and Lightning Experience Actions, click to override the predefined actions.
    4. Click Mobile & Lightning Actions in the palette and then drag the Close Opportunity action to the Salesforce Mobile and Lightning Experience Actions section.
      Add the action to the Opportunity layout
    5. Click Save.
To test your new global action, force a reload of your Salesforce mobile app. Then navigate to an opportunity record, tap Action Menu icon to access the action menu, and tap the Close Opportunity action. You should see your page, ready to close the opportunity.
The Close Opportunity action page

Naturally, you’re a sales rock star, so go ahead and close that opportunity as won. But before we start spending that commission check, there’s some additional work to do.

Style the Action Page for Mobile Devices

Use the Salesforce Lightning Design System (SLDS) to style the action’s Visualforce page to optimize it for mobile devices and to match the Salesforce app.

Once again it’s time to update the look and feel of the page.

  1. Open the Developer Console and click File | Open to open your page.
  2. Replace any markup with the following code.
    <apex:page standardController="Opportunity" 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" lang="en">
        <head>
          <meta charset="utf-8" />
          <meta http-equiv="x-ua-compatible" content="ie=edge" />
          <title>SLDS CloseOpportunity Page in Salesforce Mobile</title>
          <meta name="viewport" content="width=device-width, initial-scale=1" />
    
          <!-- Import the Design System style sheet -->
          <apex:slds />
        </head>
    
        <apex:remoteObjects >
          <apex:remoteObjectModel name="Opportunity" fields="Id,Name"/>
        </apex:remoteObjects>
    
        <body>
    
          <!-- REQUIRED SLDS WRAPPER -->
          <div class="slds-scope">
    
            <!-- PRIMARY CONTENT WRAPPER -->
            <div class="myapp">
    
              <!-- CREATE BUTTONS -->
    
                <div class="slds-grid slds-wrap">
                  <div class="slds-col slds-size--1-of-1">
                    <div class="slds-box slds-box_x-small slds-text-align_center slds-m-around--x-small slds-theme_default" 
                                onclick="closeOpportunity('Closed Won')">Won</div> 
    
                  </div>
                  <div class="slds-col slds-size--1-of-1">
                    <div class="slds-box slds-box_x-small slds-text-align_center slds-m-around--x-small slds-theme_default" 
                                onclick="closeOpportunity('Closed Lost')">Lost</div>
                  </div>
                </div>
    
              <!-- / CREATE BUTTONS  -->
    
            </div>
            <!-- / PRIMARY CONTENT WRAPPER -->
    
          </div>
          <!-- / REQUIRED SLDS WRAPPER -->
    
          <!-- IMPORT PUBLISHER SDK -->
    
          <script src='/canvas/sdk/js/publisher.js'></script>  
    
          <!-- / IMPORT PUBLISHER SDK -->
    
          <!-- JAVASCRIPT -->
    
          <!-- / JAVASCRIPT -->
        </body>
      </html>
    </apex:page>
    This code creates the buttons and styles the page to match the Salesforce app’s look.
    Note

    Note

    We explain SLDS markup in depth in the Use SLDS in Visualforce Pages in the Salesforce app unit.

  3. Add the follow code under <!-- JAVASCRIPT -->. This is the JavaScript code you wrote earlier in the unit.
      <script>
      var opportunityId = "{!Opportunity.Id}";
    
    function closeOpportunity(stageName) {
      var opportunity = new SObjectModel.Opportunity();
      opportunity.update([opportunityId], {StageName: stageName}, function(error, records) {
        if (error) {
          alert(error.message);
        } else {
          Sfdc.canvas.publisher.publish({ name: "publisher.close", payload: {refresh:"true"}});
        }
      });
    }
    </script>
  4. Reload the app and view your changes.
    The Latest Accounts page after mobile styling

We might sound like a broken record by now, but the styling changes you’ve implemented significantly improve the usability of the action you’re creating, with little effort. Great work!

Resources

Lightning bolt icon used to indicate that the content is for Lightning Experience

Remember, this module is meant for Lightning Experience. When you launch your hands-on org, switch to Lightning Experience to complete this challenge.

retargeting