Start tracking your progress
Trailhead Home
Trailhead Home

Access Salesforce Data in Hybrid Apps

Learning Objectives

After completing this unit, you’ll be able to:

  • Use the force.js library to access the Salesforce REST API from a hybrid app
  • Use Apex controllers to access Salesforce data from a hybrid remote app

Accessing the Salesforce API with Force.js

In our survey of the ContactExplorer app, you saw the force.js library at work. This library provides a rich function set for performing operations on Salesforce records. In addition to create, delete, update, and upsert, it supports SOQL queries, SOSL searches, metadata describes, and file management.

You can download force.js and other Mobile SDK JavaScript libraries from the SalesforceMobileSDK-Shared/libs and SalesforceMobileSDK-Shared/dependencies GitHub repos.

Although this trail focuses on hybrid local apps—that is, hybrid apps that are self-contained on the mobile device—you can also create hybrid remote apps. A hybrid remote app loads Visualforce pages from the Salesforce server, reformats them, and displays them on mobile devices. The source code can remain on the server or be split between the server and the device.
Note

Note

When you create a hybrid remote app, the forcehybrid script prompts you for a Start page. Enter the relative path to your Visualforce landing page, beginning with /apex/. For example: if your landing page address is https://<instance>.visual.force.com/apex/BasicVFPage, enter /apex/BasicVFPage

Getting Started with force.js and Mobile SDK

To get started, upload your essential app resources to the Salesforce cloud.

  1. Create an archive file, such as a ZIP file, that contains cordova.js, force.js, and any other static resources your project requires.
  2. In Salesforce, upload the archive file via Your Name | App Setup | Develop | Static Resources.

A Simple Visualforce Page Example

The following code shows a simple Visualforce page defined almost entirely with Apex and JavaScript code. The logic follows the same outline as the ContactsApp JavaScript code. It loads force.js, initializes the session, and then passes a SOQL query to the asynchronous force.query() method. If the query succeeds, the app displays the first retrieved Name field in an HTML <span> tag.
<apex:page docType="html-5.0" sidebar="false" showHeader="false" 
    contentType="text/html" applyHtmlTag="false" applyBodyTag="false" 
    standardStylesheets="false" cache="true">

<html>
    <head>
      <meta charset="utf-8"></meta>
      <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no"></meta>
      <apex:includeScript value="{!URLFOR($Resource.Easy, 'cordova/cordova.js')}"  />
      <apex:includeScript value="{!URLFOR($Resource.Easy, 'libs/force.js')}"  />

      <script>
(function() {
    /* Do login */
    force.login(
        function() {
            console.log("Auth succeeded"); 
            showUsersList();
        },
        function(error) {
            console.log("Auth failed: " + error); 
        }
    );

    /* This method will render a list of users from current salesforce org */
    var showUsersList = function() {

        fetchRecords(function(data) {
            var users = data.records;

            var listItemsHtml = '';
            for (var i=0; i < users.length; i++) {
                listItemsHtml += ('<li class="table-view-cell"><div class="media-body">' + 
                    users[i].Name + '</div></li>');
            }

            document.querySelector('#users').innerHTML = listItemsHtml;
        })
    }

    /* This method will fetch a list of user records from salesforce. 
    Just change the soql query to fetch another sobject. */
    var fetchRecords = function (successHandler) {
        var soql = 'SELECT Id, Name FROM User LIMIT 10';
        force.query(soql, successHandler, function(error) {
            alert('Failed to fetch users: ' + error);
        });
    };

})();
      </script>
    </head>
    <body>

      <header>
         <h1>Hello, Visualforce!</h1>
      </header>

        <!-- Placeholder to add users list -->

      <ul id="users">
      </ul>

      <p>Welcome to Mobile SDK.</p>
    </body>
</html>
</apex:page>

Using Apex Controllers in a Hybrid Remote App

With hybrid remote apps, you typically access Salesforce data through a Visualforce page and its associated Apex controller. If your Visualforce page contains JavaScript code, that code can interact and share data with the server-side Apex controller.

Apex supports the following two means of invoking Apex controller methods from JavaScript: Both techniques use an AJAX request to invoke Apex controller methods directly from JavaScript. The JavaScript code must be hosted on a Visualforce page.
In comparison to apex:actionFunction, JavaScript remoting offers several advantages.
  • It offers greater flexibility and better performance than apex:actionFunction.
  • It supports parameters and return types in the Apex controller method, with automatic mapping between Apex and JavaScript types.
  • It uses an asynchronous processing model with callbacks.
  • Unlike apex:actionFunction, the AJAX request does not include the view state for the Visualforce page. This results in a faster round trip.
Compared to apex:actionFunction, however, JavaScript remoting requires you to write more code.

The following example inserts JavaScript code in a <script> tag on the Visualforce page. This code calls the invokeAction() method on the Visualforce remoting manager object. It passes invokeAction() the metadata needed to call a function named getItemId() on the Apex controller object objName. Because invokeAction() runs asynchronously, the code also defines a callback function to process the value returned from getItemId(). In the Apex controller, the @RemoteAction annotation exposes the getItemId() function to external JavaScript code.

//Visualforce page code
<script type="text/javascript">
     Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.MyController.getItemId}',
        objName,
        function(result, event){
            //process response here
        },
        {escape: true}
    );
<script>

//Apex Controller code

@RemoteAction
global static String getItemId(String objectName) { ... }

In the getItemId() method, for example, you can call a Salesforce API and capture the return value in JavaScript.

retargeting