Look Ma – No Apex: Mobile Apps with RemoteObjects and Mobile SDK

At Dreamforce 15, I will have the honour of speaking at the Mobile Theatre at 4.30pm on Day One (Tuesday September 15). The topic is mobile development on Salesforce – and creating your first app with the Salesforce Mobile SDK. And no apex is required.

Here is the slide deck for the presentation.

When introducing developers to Apex, one of the key points is that Apex is only used when you need it. Where you can take advantage of the Declarative and built-in features of the platform to fulfill requirements, then thats the optimum solution.

I also try to introduce developers to new development features where possible, and it was while bringing one of my classes through Visualforce Remote Objects that I got the inspiration to make a Mobile SDK app. I also owe James Steer a lot of credit for giving me example code that got me thinking.

The App: Project Timesheets
Blue Wave Technology (who I work for) use Salesforce to manage the business of winning Opportunities, managing project requirements and delivering for customers. The data model used is actually pretty simple; Opportunity records are won from which Project records are created to plan and schedule pieces of work. Blue Wave’s consultants then create Project Timesheet records to indicate work done and time spent on a project.

Project Timesheets Data Model

Project Timesheets Data Model

I wanted to take this model and make a simple but effective app that would allow me to update my project timesheet records quickly. I wanted to create a task-focussed app (ie manage my timesheets) that had our corporate logos and look & feel that had a familiar SPA (Single Page Application) architecture.

I also wanted to show other developers who may not have made mobile apps before how it is created so I stuck to a skill set that I see as common to many developers on the platform:

I also used c3.js to make charts.

The app required the installing and using Salesforce Mobile SDK to create a Hybrid Remote app, a process which doesn’t involve any extra code. Just follow the steps in this Trailhead Module and point to a Visualforce page.

The Visualforce Page:
The entire app is contained in a single Visualforce page. I also use a static resource to bring in AngularJS and a javascript library to handle the tables. We also add extra fields to the Opportunity object and add 2 custom objects – Project__c and Project_Timesheet__c. These can be installed by installing this managed package.

The Visualforce page is quite long – almost 2000 lines – and really the javascript code should be split into separate JS files but it may be easier to follow at first in one page. It is typical for an AngularJS developer to use a structure like angular-seed and tools like bower to manage a project – but I have omitted this here.

The Code: Remote Objects
The page has no controller and relies on AngularJS for its logic, routing and interface. It uses javascript to retrieve, display and manage records in Salesforce using Visualforce Remote Objects.

Remote Objects are proxy objects defined by Visualforce tags and allow for basic querying and DML on the defined objects and fields via javascript. A single tag can contain child tags – one for each sObject in Salesforce. The API name of the sObject and the fields we want to include are defined in the remoteObjectModel tag.

Defining the remoteObjects tag

Defining the remoteObjects tag

To work with a remoteObjectModel in Javascript, define a javascript object and declare it as a new instance of a defined RemoteObjectModel tag in the page. A shorthand local variable can be used here instead of the API name of the Salesforce object.

Defining a JavaScript Object from a RemoteObjectModel

Defining a JavaScript Object from a RemoteObjectModel

The javascript objects can then be used to query for records. Query parameters, ordering, limit and offsets can be used. RemoteObjectModel has a retrieve method that executes queries and returns an error or an array of records in JSON. These can then be pushed into a javascript array for display.

Querying records with RemoteObjectModel

Querying records with RemoteObjectModel

To create a new record or update an existing record the RemoteObjectModel has insert, update, delete and upsert methods. It should be noted that a RemoteObjectModel can include formula fields which cannot be edited, so (as in the below example) a new javascript object should be created and values set within it in order to process the DML event.

Upserting a record with RemoteObjectModel

Upserting a record with RemoteObjectModel

Step-by-Step: Re-create the Project Timesheets Application

Most of the steps here are listed in the Getting Started with Hybrid Development trailhead module.

1. In your developer org install this unmanaged package (https://login.salesforce.com/packaging/installPackage.apexp?p0=04t24000000A459). The metadata is also available on github.

2. Install the Salesforce Mobile SDK along with its pre-requisites (See Installing Mobile SDK for Hybrid Development in link above).
Note: A good way to Install Ant is via homebrew
3. Create a Connected App in your org (see previous link). Ensure to copy out the Consumer Key and the callback URI.
4. Using Terminal or the Command Prompt, navigate to a directory where the application is to be saved
5. Create a Hybrid_Remote app with the command forcedroid create or forceios create.
6. These processes will ask for some settings as follows:

  • Application type: hybrid_remote
  • Application name: ProjectTimesheets
  • Output directory: ProjectTimesheets
  • Package name: com.company.projectTimesheets
  • (forceios only) Organization name: Company Inc
  • Start Page for app: /apex/projectTimesheetsConsole
  • (forceios only) Connected App ID: Paste the consumer key from your connected app
  • (forceios only) Connected App Callback URI: Paste the callback URL from your connected app

6. (forcedroid only) In your project directory, open the www/bootconfig.json file in a UTF-8 compliant text editor and replace the values of the following properties:

  • remoteAccessConsumerKey: Paste the consumer key from your connected app
  • oauthRedirectURI: Paste the callback URL from your connected app

7. Create icons and splash screens to add your branding to the app on the device by adding a graphic to http://ticons.fokkezb.nl/. Use a large graphic and follow the margin and centering recommendations on the site. Replace the folders in your application directory (look for a resources sub-folder) with the folders returned.
8. Run the app by adding it to XCode or Eclipse and running on a real or virtual device.

I am including screenshots of the app here:

My Current Project Timesheets

My Current Project Timesheets

Creating a Timesheet

Creating a Timesheet

Chart of Project Activities (c3.js)

Chart of Project Activities (c3.js)

My Project Timesheets - on iPhone

My Project Timesheets – on iPhone

Here is the slide deck for the presentation.


Speaking at Dreamforce 15

I am speaking at Dreamforce in San Francisco next week. I’m on the Mobile Theatre on Tuesday at 4.30pm (Pacific Time).

I will be showing (and giving away) the code and metadata for a Salesforce Mobile SDK application which should be especially useful for developers who have never created a Mobile SDK app before.

The app is contained in a single Visualforce page with no apex controller required and I only used those frameworks and tools the majority of developers have or can pick up very quickly:

  • Visualforce
  • HTML5
  • CSS3
  • Bootstrap
  • AngularJS v1.x
  • C3.js (for charting)

I will be posting the full instructions here over the weekend on how to get and install the code and metadata in your org.

Developer News and Useful Links from Dreamforce 14:

I’ll post a few things on Dreamforce 14 over the next few weeks, but a lot of very interesting things have been announced.


Announced this morning in the Developer Keynote, Trailhead is a new section in developer.salesforce.com that allows developers to get started on the platform. There’s already a lot there with the promise of a lot more.



The buzz word of the conference among developers, Lightning is a new set of meta data elements developers can create that essentially add custom capabilities to the setup menu. So, a developer can create a Lightning App containing components that can be then added to your Salesforce apps in the set up menu.

A lot of what has been shown shows it’s massive potential but it’s obvious that Salesforce are still finishing off so that all orgs can see it in Spring 15. Lightning is only available in Dev orgs in Winter 15 but to see where development is going is very interesting:

And you can win some money as early adopters via topcoder:


What is really interesting is that Salesforce are creating tools for development and setup in Lightning. Though only available by request, I have had a quick look at the new ‘Lightning Process Builder’ which will allow the creation of Visual Workflows (it has the best UI I’ve seen) and the ‘Lightning App Builder’ which will give Admins and Developers an easy way to ad Lightning Components and Apps to their UIs. The Process Builder looks pretty finished already and the App Buillder shows huge promise.


Heroku DX was launched this week. Also a big push on easily creating heroku apps and sharing boilerplate applications.


I heard something at a presentation this morning that was news to me. [SAFE HARBOUR] DML limits will completely change in Spring 15. Instead of counting calls and records per transaction, the new limit will look at the length of time of the transaction (like CPU limit). Seems that this will become the norm for all limits.


[SAFE HARBOUR] again, but Apex developers could get more control over the order of execution of things than they had before and it sounded like this will happen next year. Lots of reading between lines here but it sounds great!

External Objects

Apart from Lightning, External Objects are the best thing I’ve seen this week. Retrieving data from an external database and treating it as a custom object in Salesforce. Very impressive.