Manage Navigation
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
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 and Messaging 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
- Trailhead: Navigation and Setup in Lightning Experience
- Trailhead: Customization: Create Custom Buttons and Links
- Visualforce Developer Guide: PageReference Class
- Visualforce Developer Guide: Dynamic References to Action Methods Using $Action
- Salesforce Mobile App Developer Guide: Navigation and Messaging with the sforce.one Object