27

Actually I am using lightning components with a visualforce page, because this is the only way to override standard button (using VF) today. The problem is that, i need to redirect my user to the new record page on a certain action, but :

$A.get("e.force:navigateToURL")

and

$A.get("e.force:createRecord");

Is not working. Because as stated in the doc :

"This event is handled by the one.app container. It’s supported in Lightning Experience and Salesforce1 only."

But the worst part is that even if I am in lightning experience, but the fact that i'm using a VF, it is considering me out of lightning.

But for such cases, what salesforce has to provide for navigation ? Is there no method I can use for this redirection ?

3 Answers 3

28

I ran into the same issue. I have Lightning Components I want to use in VF pages AND in Lightning apps running in the Lightning Experience. I also didn't want to update the components to check to see which environment they were running in (no isSalesforce1, isVF, isLightning checks in any components). Ideally, the components raise the navigation events, and they work regardless of whether the host is the one.app container or a VF page.

After some digging, I got this working. The first step is to get the navigation events firing properly in the components. The code below assigns null to the event variable when running in a VF page because the force namespace library hasn't been loaded. The result is an error in the browser.

var event = $A.get('e.force:navigateToObjectHome');

event.setParams({
    scope: 'Contact'
});

event.fire();

Fortunately, the fix is straightforward. Add the dependency to your Lightning dependency app.

<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:myLightningComponent"/>
    <!-- Load the navigation events in the force namespace. -->
    <aura:dependency resource="markup://force:*" type="EVENT"/>
</aura:application>

With this change, the navigation events will fire properly in your components; however there's still a problem. Nothing happens. This brings us to the second step which is to add handlers for these events in the VF host page. These handlers will explicitly perform navigation by either calling the appropriate sforce.one method or setting window.location. You can set up the handlers in the VF page after the component is created. For example, you can handle the force:navigateToObjectHome event with the following code:

$Lightning.use("c:myLightningComponentDep", function() {
    var attributes = {}; // Set component attributes here

    $Lightning.createComponent('c:myLightningComponent', attributes, 'myLightningComponent',
        function(cmp) {
            $A.eventService.addHandler({
                event: 'force:navigateToObjectHome',
                handler: function(event) {
                    if (sforce && sforce.one) {
                        // VF page in S1 or Lightning Exp
                        sforce.one.navigateToObjectHome(event.$params$.scope);
                    } else {
                        // VF page in Classic
                        // Ugg! We need an if branch for each possible object type.
                        // Is there a better way of doing this?
                        if (event.$params$.scope === 'Contact') {
                            window.location = '{!URLFOR($Action.Contact.Tab, $ObjectType.Contact)}';
                        }
                    }
                }
            });
    });
});

This approach has worked well for me, and it has the added benefit of requiring no changes to the Lightning components. I haven't gotten this working in Salesforce1 yet as my organization doesn't use Salesforce1, although I assume the approach is similar.

5
  • 3
    I turned this answer into a blog post which you can find at joebuschmann.com/…
    – Joe B
    Commented Jan 16, 2017 at 16:11
  • With Locker Service on I get "Cannot set property location of [object Object] which has only a getter" when setting window.location; looks like it now has to be window.location.href.
    – Keith C
    Commented Apr 24, 2017 at 14:26
  • 1
    There are several concerns everyone should be aware: 1) You cannot access to the event parameters using this structure: event.$params$.nameOfParameter. Now params are under event.pc. 2) When you run this page in classic interface you will get exception that sforce is not defined. So you must add this line to your VF page <script src="/soap/ajax/43.0/connection.js"></script>
    – Tehn-r
    Commented Jul 20, 2018 at 20:42
  • 1
    I just needed to apply this approach today, and nearly as laid out above, but like Tehn-r mentioned, you need to include the connector.js script, but for me the params are "event.Zb.xxxx". Not sure why SFDC is changing them, but this worked for me.
    – Tezyn
    Commented Mar 27, 2020 at 23:12
  • @JoeB Why do you have to make the component an aura:dependency in the app defintion? Commented Sep 7, 2020 at 21:23
10

Here is what I use on my page/template to control navigation based on the theme of the current context.

    <script>
        function goHome(){
            ForceUI.isSalesforce1() ? sforce.one.navigateToURL('/home/home.jsp',true) : window.location.href='/';
        }

        function goretURL(){
            ForceUI.isSalesforce1() ? sforce.one.navigateToURL('{!$CurrentPage.parameters.retURL}') : window.location.href='{!$CurrentPage.parameters.retURL}';
        }

        function gotoURL(u, isParent){ //isParent indicates the parent window should be redirected (think inline vf page)
            ForceUI.isSalesforce1() ? sforce.one.navigateToURL(u) : (isParent ? window.top.location.href = u : window.location.href=u);
        }


        (function(myContext){
            myContext.ForceUI = myContext.ForceUI || {};

            myContext.ForceUI.isSalesforce1 = function() {
                return((typeof sforce != 'undefined') && sforce && (!!sforce.one));
            }
        })(this);

    </script>

The last part of the code was used directly from here: https://developer.salesforce.com/docs/atlas.en-us.salesforce1.meta/salesforce1/vf_dev_best_practices_pages_multipurpose.htm

Not sure how applicable this will be to you since we do not see your page / component etc but if it can be used great.

1
  • 1
    @AnnappaPH This comment is not really appropriate. Please do not make these sorts of overtures via comment. If you would like to draw more attention to your posts, use a bounty.
    – Adrian Larson
    Commented Feb 13, 2019 at 1:09
1

You don't need to add an event handler in the VF page, you can directly use that,

sforce.one.navigateToObjectHome('sObject aka scope');

navigateTo: function(component,event,helper){
    if (sforce && sforce.one) {
        sforce.one.navigateToObjectHome('scope aka sObject');
    }
}

Using this you approach can also eliminate:

<aura:dependency resource="markup://force:*" type="EVENT"/>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .