[SalesForce] Navigate to Opportunity Record Page from a Lightining Component embedded in VF Page

I have added a Custom Lightining Component 'c:SF1ProductSearch' in a VF page. On my component i have added a Cancel button which should redirect to the Opportunity Record Detail Page in Salesforce1.

I am using force:navigateToSObject but i get am getting the error

"Uncaught error in $A.run() : Cannot read property 'setParams' of undefined"

Below is my Code:

VF Page:

<apex:page standardController="Opportunity" standardStylesheets="false" showHeader="false" sidebar="false" showQuickActionVfHeader="false">
    <link href="/resource/bootstrapsf/" rel="stylesheet"/>
     <apex:includeScript value="/lightning/lightning.out.js" />

    <div id="lightning" ></div>
       <script>       
        $Lightning.use("c:SF1AddOpportunityProduct", function() {
          $Lightning.createComponent("c:SF1ProductSearch", 
            { recordId: "{!opportunity.Id}" }, 
            "lightning",function(cmp) {
                //debugger;
            });
        });
    </script>  
</apex:page>

Lightining Component:

<ltng:require styles="/resource/bootstrap/bootstrap/dist/css/bootstrap1.css,
                          /resource/LighteningDesign/LighteningDesign/assets/styles/salesforce-lightning-design-system.css"
                  />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <!--Header Section -->
        <div class="panel-heading clearfix">
            <h4 class="panel-title pull-left" style="padding-top: 7.5px;">Search Products</h4>
            <div class="btn-group pull-right">
                <a href="#" class="btn btn-default btn-sm" onclick="{!c.goBack}">Cancel</a>
            </div>
        </div>

Client side Controller Function goBack

var oppid = component.get("v.recordId");
var navEvt = $A.get("e.force:navigateToSObject");
navEvt.setParams({
  "recordId": oppid,
});
navEvt.fire();

Grateful for any thoughts as to where im going wrong.

Best Answer

There are a couple of things going on here:

  • you would need to let the Lightning Framework know that you have a dependency on force:navigateToSObject by adding

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

    to either your component or your LO app)

  • you are no longer running inside of S1/LEX directly and the container you are in (Visualforce) does not have any logic in it to respond to that event or even listen for it. No autoforwarding/mapping of events exists yet in Visualforce but I do have a story on the backlog for this very useful feature

The good news is that its not hard to write this yourself. Basically we just need a "shim" that listens for force:navigate* and bridges to the sforce.one.navigateTo* methods that already exist in VF when running under S1/LEX.

https://developer.salesforce.com/trailhead/lex_dev_visualforce/lex_dev_visualforce_navigation

If your component only needs to work in LC4VF you have an even easier path to just use the sforce.one.navigateToSObject() API directly:

if (sforce.one) {
   sforce.one.navigateToSObject(component.get("v.recordId"));
}