trailhead

Learning Objectives

After completing this unit, you’ll be able to:
  • Describe the three “classic” Visualforce mechanisms for controlling navigation from one page to another.
  • Describe which of these techniques don’t work in Lightning Experience.
  • List at least three Lightning Experience navigation events, and how to send them.

Managing Navigation

App flow and navigation is in many ways the heart of application design. Visualforce provides a number of ways to add navigation elements and to direct application flow. Lightning Experience adds its own application flow, navigation elements, and mechanisms for affecting where users go as they use Salesforce.

The good news is that “classic” Visualforce navigation continues to work. The better news is that your Visualforce pages can take advantage of the new Lightning Experience mechanisms, too.

Navigation in Lightning Experience

Before we talk about the details of Visualforce navigation, and how you create it so that it works in Salesforce Classic and Lightning Experience, let’s talk a little about navigation in general. What do we actually mean by “navigation”?

The first thing we might mean by navigation is user interface elements on the screen. You click something, and something happens. For example, you click the Accounts item in the navigation menu, and you go to the Accounts object home page. You click the New button, and a record entry form appears. You choose a custom action from a quick actions menu, and you launch a custom process. And so on. Those buttons and menu items are navigation elements.

The design of the navigation system, the user interface in Lightning Experience, is very different from Salesforce Classic. We’re not going to talk about those differences here, but you’ll want to be familiar with where everything moves when you switch between the two user experiences. You can learn more about that right here in Trailhead, in the Navigating Lightning Experience and Setup unit.

Another, less visible kind of navigation is the “something happens” part of the above. Behind the scenes, Salesforce decides what’s going to happen when you select an item in a menu, or click a link or button. Much of this navigation is built into Salesforce already, while other aspects are customizable—for example, overriding actions with Visualforce pages. But all of this navigation is managed by code written by Salesforce.

And then there’s navigation in your own apps—apps that use your code to control application flow. When your custom action opens a form and the user clicks save, where do you go? When your running code makes a decision about where the user should go next, and sends them there. This is what we’re going to talk about in this unit.

Classic Visualforce Navigation

“Classic” Visualforce navigation can be boiled down to “what happens at the end of an action method.” Action methods return a PageReference object with the details of where the user is to be navigated to, and then the Visualforce framework handles the details of sending the right response back to the user’s browser. And, great news, all of this still works.

Remember also that the Standard Controller returns a PageReference from its action methods. So, your existing navigation, whether you’re using the Standard Controller or your own custom controller code, continues to work as you expect.

Modern Visualforce Navigation

So, if classic Visualforce navigation works, why are we still talking about this? What are we even having a conversation about? We just want to say one word to you. Just one word. Are you listening? … “JavaScript.”

There’s a great future in JavaScript—and that future is here today. Many Visualforce developers are using JavaScript heavily in their apps, and that use continues to grow. Classic Visualforce works, and will continue to work for a long time. But as developers adopt Visualforce features such as Remote Objects and JavaScript remoting, more of their apps’ behavior migrates from the server side, where PageReference is the rule, to the browser and JavaScript, where there’s no such thing as a PageReference.

In the Lightning Experience (and the Salesforce app) world, there are rules and tools for building navigation in JavaScript. We’ll cover the rules, which are mostly about what not to do, in a little bit. Let’s talk about the right way to do things first.

Lightning Experience manages navigation using events. The navigation event framework is made available as a JavaScript utility object that provides a number of functions that make creating programmatic navigation straightforward. The sforce.one object is automatically added to Visualforce pages when they run in Lightning Experience. This object provides a number of functions that trigger navigation events when the functions are called. To use these functions, you can call them directly from your page’s JavaScript code, or you can attach calls as click (or other) handlers to elements on the page.

Important

Important

The sforce.one object isn’t available in Salesforce Classic. Any code that uses it should test for the existence of sforce.one first.

The sforce.one object provides the following functions. Reference the function using dotted notation from the sforce.one object. For example: sforce.one.navigateToSObject(...).
Function Description
back(​[refresh]) Navigates to the previous state that’s saved in the sforce.one history. It’s equivalent to clicking a browser’s Back button.
navigateToSObject(​recordId​[, view]) Navigates to an sObject record, specified by recordId.
navigateToURL(​url​[, isredirect]) Navigates to the specified URL.
navigateToFeed(​subjectId, type) Navigates to the feed of the specified type, scoped to the subjectId.
navigateToFeedItemDetail(​feedItemId) Navigates to the specific feed item, feedItemId, and any associated comments.
navigateToRelatedList(​relatedListId, parentRecordId) Navigates to a related list for the parentRecordId.
navigateToList(​listViewId​, listViewName, scope) Navigates to the list view that’s specified by the listViewId, which is the ID of the list view to be displayed.
createRecord(​entityName​[, recordTypeId]) Opens the page to create a new record for the specified entityName, for example, “Account” or “MyObject__c”.
editRecord(​recordId) Opens the page to edit the record specified by recordId.

For additional details about using these functions, and the parameters they accept, see Navigation with the sforce.one Object in this unit’s Resources.

Navigation Gotchas, and How to Fix Them

The first rule for building Visualforce navigation in JavaScript is: do not set window.location directly. The second rule for building Visualforce navigation in JavaScript is: do not set window.location directly.

Don’t Set window.location Directly

OK, gratuitous repetition and movie reference aside, what’s the big deal here? It’s pretty simple. When in Lightning Experience your page doesn’t have a window.location to set! Remember all the earlier discussion about the Visualforce “container,” and being in an iframe, and Lightning Experience being some kind of health club? (SPA—single-page application.) This is one of the things that falls out of it. The Visualforce iframe doesn’t have direct access to the window.location value, so you can’t set it. If your code depends on setting it, it’ll break. That is, actions that fire navigation by setting window.location will simply stop navigating to wherever you were expecting to go.

There’s actually a way around this restriction, but you shouldn’t use it. The reason is if you bypass the navigation functions in sforce.one, your navigation events won’t be tracked in the Lightning Experience navigation stack. That stack provides useful features, like Back buttons that account for redirects and the like. A number of features in Lightning Experience (and especially in the Salesforce app) depend on that stack containing all navigation events. It’s worth making sure you use it correctly.

The Salesforce Classic Issue

So, yeah, there’s this one…thing. Unfortunately, the sforce.one utility object isn’t available when your page runs in Salesforce Classic. In that context, you have to use window.location. The good news is, in Salesforce Classic, window.location is available. The bad news is, this limitation means you’ll have to add an ugly if block to your code. Consider wrapping your navigation functions in utility methods that deal with this complexity, so that your main navigation logic can be straightforward.

Static URLs

Don’t use static URLs to Salesforce resources. That is, if you’re adding a link to edit a Contact record, don’t create the link by building a string with a static pattern like link = '/' + accountId + '/e'. In some contexts this works, but in others it doesn’t. Instead, try one of these approaches:
  • In Visualforce markup, use {!URLFOR($Action.Contact.Edit, recordId)}
  • In JavaScript, use navigateToSObject(recordId)
There are actions and functions for viewing, creating, editing, and so on. Use them, rather than URL strings.

Resources

Time Estimate
retargeting