function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
KIBLKIBL 

Launch a visualforce page in Lightning

How can I auto lauch a visual force page in Lightning from an action button that calls a controller and redirects to a custom object and stays in lightning?  I need all this to happen in one click.

We currently have a process that takes the values from the opportunity and populates a custom object.  This process uses field ID's to map the values to a custom object.  The existing button does not appear in "Lightning Experience."  The only way that is obvious to accomplish this task in the "Lightning Experience" is to utilize a visual force page. The user should click a Lightning Experience "Action" button.  The page should launch automatically, execute code in the controller and return to the visual force page to "navigatetoSObject."   It is important that the user has a limited number of clicks that they have to execute.  The "navigatetoSObject" is necessary so the user is not forced back into "Salesforce Classic" mode.  If a PageReference is executed in the controller "Salesforce Classic" appears even though the user has chosen to be in the "Lightning Experience." 


 
Best Answer chosen by KIBL
KIBLKIBL
This is what was the resolution for me.
<apex:page standardController="Account" extensions="createOpportunityfromAccount"  showQuickActionVfHeader="false"> 
<!-- The actionFunction is activated by the buildURL java script call on page load. 
When the actionFunction is activated, the method "autorun" in controller createOpportunityFromAccount is  
fired.  The return value of null is needed to return to the page. When the actionFunction re-render
is executed the page is redirected to the opportunity the controller just created. -->
<script>
         	onload = function() { buildURL(); };
</script>
<apex:pageBlock >
<apex:pageBlockSection title="Create Opportunity From Account" columns="1" >
<apex:outputPanel id="jspanel">
<script type="text/javascript">
 			   var theURL = '{!theBuiltURL}';
               if ( (typeof sforce != 'undefined') && sforce && (!!sforce.one) )   {
                    sforce.one.navigateToSObject(theURL);
               } else {
                    window.location.href = '/006/e?theURL';
               }               
</script>
</apex:outputPanel>  
</apex:pageBlockSection>
</apex:pageBlock>
<apex:form >
	<apex:actionFunction name="buildURL" action="{!autoRun}" rerender="jspanel" >
    </apex:actionFunction>
</apex:form>
</apex:page>

And the Controller.
 
public with sharing class createOpportunityfromAccount {
//Define the Order Management Object
Account theAccount = new Account();
Opportunity theOpportunity = new Opportunity();   
String theOpportunityID = ''; 
String theAccountID = ''; 
List<Opportunity> OpportunityInsert  = new List<Opportunity>();
//This is very important.  It allows the page the see the variable 
public String theBuiltURL {get;set;}

// Constructor - This only matters if the autoRun function doesn't work right     
public createOpportunityfromAccount(ApexPages.StandardController stdController) {        
this.theAccount = (Account)stdController.getRecord();     
} 
// Code invoked on page load.      
public PageReference autoRun()
{           
String theAccountID = ApexPages.currentPage().getParameters().get('id'); 
if (theAccountID == null) 
{             
// Display the Visualforce page's error message if no Id is passed over             
return null;         
} 
List<Account> TheAccountList = [select Id, Name, Market_Code__c, Sales_Rep__c, Field_Sales_Rep_Number__c, KI_Customer__c, Region__c, District__c, District_Name__c, District_Type__c from Account where id =:theAccountID  Limit 1];
for(Account theAccount: TheAccountList)
{ 
theOpportunity.AccountId = theAccount.Id;    
theOpportunity.StageName = '25';
theOpportunity.Name = theAccount.Name;
Date theCloseDate = system.today();
theOpportunity.CloseDate =  theCloseDate.addYears(1); 
theOpportunity.Amount = 1;
 
if (theAccount.Market_Code__c != null ) {
theOpportunity.Market_Code__c = theAccount.Market_Code__c;  
}

if (theAccount.Sales_Rep__c != null ) {
theOpportunity.Sales_Representative__c = theAccount.Sales_Rep__c;  
}

if (theAccount.Field_Sales_Rep_Number__c != null ) {
theOpportunity.Field_Sales_Rep_Number__c = theAccount.Field_Sales_Rep_Number__c;  
}

if (theAccount.KI_Customer__c != null ) {
theOpportunity.KI_Customer__c = theAccount.KI_Customer__c;  
}

if (theAccount.Region__c != null ) {
theOpportunity.Region__c = theAccount.Region__c;  
}

if (theAccount.District__c != null ) {
theOpportunity.District__c = theAccount.District__c;  
}

if (theAccount.District_Name__c != null ) {
theOpportunity.District_Name__c = theAccount.District_Name__c;  
}

if (theAccount.District_Name__c != null ) {
theOpportunity.District_Name__c = theAccount.District_Name__c;  
}

if (theAccount.District_Type__c != null ) {
theOpportunity.District_Type__c = theAccount.District_Type__c;  
}
    insert theOpportunity;
    theBuiltURL =   theOpportunity.id;
}

return null; 
      
} 

}


 

All Answers

sharathchandra thukkanisharathchandra thukkani
for me page reference works in lightening to redirect to some other page.
sharathchandra thukkanisharathchandra thukkani
what error do you get?
Amit GoyalAmit Goyal
Hi KIBL,

you will need to use a additional javascript code to identify the environment in which your visualforce page is running [SalesForce Classic / Lightning Experience] by the sforce.one utility

function isLightningExperienceOrSalesforce1() {
return((typeof sforce != 'undefined') && sforce && (!!sforce.one));
}

if( isLightningExperienceOrSalesforce1() ) {
// Do something for Lightning Experience
}
else {
// Use classic Visualforce
}

and instead of PageReference or hardcoded string you could use $Action methods on your page.

The following trailheads could be helpful for you.

https://developer.salesforce.com/trailhead/lex_dev_visualforce/lex_dev_visualforce_multipurpose_pages
https://developer.salesforce.com/trailhead/lex_dev_visualforce/lex_dev_visualforce_process

Please mark this question if it helps and answered your question.

Thanks.
KIBLKIBL
This is what was the resolution for me.
<apex:page standardController="Account" extensions="createOpportunityfromAccount"  showQuickActionVfHeader="false"> 
<!-- The actionFunction is activated by the buildURL java script call on page load. 
When the actionFunction is activated, the method "autorun" in controller createOpportunityFromAccount is  
fired.  The return value of null is needed to return to the page. When the actionFunction re-render
is executed the page is redirected to the opportunity the controller just created. -->
<script>
         	onload = function() { buildURL(); };
</script>
<apex:pageBlock >
<apex:pageBlockSection title="Create Opportunity From Account" columns="1" >
<apex:outputPanel id="jspanel">
<script type="text/javascript">
 			   var theURL = '{!theBuiltURL}';
               if ( (typeof sforce != 'undefined') && sforce && (!!sforce.one) )   {
                    sforce.one.navigateToSObject(theURL);
               } else {
                    window.location.href = '/006/e?theURL';
               }               
</script>
</apex:outputPanel>  
</apex:pageBlockSection>
</apex:pageBlock>
<apex:form >
	<apex:actionFunction name="buildURL" action="{!autoRun}" rerender="jspanel" >
    </apex:actionFunction>
</apex:form>
</apex:page>

And the Controller.
 
public with sharing class createOpportunityfromAccount {
//Define the Order Management Object
Account theAccount = new Account();
Opportunity theOpportunity = new Opportunity();   
String theOpportunityID = ''; 
String theAccountID = ''; 
List<Opportunity> OpportunityInsert  = new List<Opportunity>();
//This is very important.  It allows the page the see the variable 
public String theBuiltURL {get;set;}

// Constructor - This only matters if the autoRun function doesn't work right     
public createOpportunityfromAccount(ApexPages.StandardController stdController) {        
this.theAccount = (Account)stdController.getRecord();     
} 
// Code invoked on page load.      
public PageReference autoRun()
{           
String theAccountID = ApexPages.currentPage().getParameters().get('id'); 
if (theAccountID == null) 
{             
// Display the Visualforce page's error message if no Id is passed over             
return null;         
} 
List<Account> TheAccountList = [select Id, Name, Market_Code__c, Sales_Rep__c, Field_Sales_Rep_Number__c, KI_Customer__c, Region__c, District__c, District_Name__c, District_Type__c from Account where id =:theAccountID  Limit 1];
for(Account theAccount: TheAccountList)
{ 
theOpportunity.AccountId = theAccount.Id;    
theOpportunity.StageName = '25';
theOpportunity.Name = theAccount.Name;
Date theCloseDate = system.today();
theOpportunity.CloseDate =  theCloseDate.addYears(1); 
theOpportunity.Amount = 1;
 
if (theAccount.Market_Code__c != null ) {
theOpportunity.Market_Code__c = theAccount.Market_Code__c;  
}

if (theAccount.Sales_Rep__c != null ) {
theOpportunity.Sales_Representative__c = theAccount.Sales_Rep__c;  
}

if (theAccount.Field_Sales_Rep_Number__c != null ) {
theOpportunity.Field_Sales_Rep_Number__c = theAccount.Field_Sales_Rep_Number__c;  
}

if (theAccount.KI_Customer__c != null ) {
theOpportunity.KI_Customer__c = theAccount.KI_Customer__c;  
}

if (theAccount.Region__c != null ) {
theOpportunity.Region__c = theAccount.Region__c;  
}

if (theAccount.District__c != null ) {
theOpportunity.District__c = theAccount.District__c;  
}

if (theAccount.District_Name__c != null ) {
theOpportunity.District_Name__c = theAccount.District_Name__c;  
}

if (theAccount.District_Name__c != null ) {
theOpportunity.District_Name__c = theAccount.District_Name__c;  
}

if (theAccount.District_Type__c != null ) {
theOpportunity.District_Type__c = theAccount.District_Type__c;  
}
    insert theOpportunity;
    theBuiltURL =   theOpportunity.id;
}

return null; 
      
} 

}


 
This was selected as the best answer
David Roberts 4David Roberts 4
Thanks, Amit,
I was able to get from those links the code:
var pageName = 'MyVisualforcePageName';
$A.get("e.force:navigateToURL").setParams(   {"url": "/apex/" + pageName}   ).fire();
However, navigateToURL is superceded (according to: documentation (https://developer.salesforce.com/docs/component-library/bundle/force:navigateToURL/documentation)) by Lightning:navigate
components_navigation_web_page (https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_navigation_web_page.htm)
so the code becomes:
var pageName = '/apex/myVFPageName';
var navService = component.find("navigationService");
var pageReference = {
     type: 'standard__webPage',
     attributes: {
            url: pageName,
      }
};
event.preventDefault();
navService.navigate(pageReference);
Don't forget to put
<lightning:navigation aura:id="navigationService" />
in your component definition.
By using different PageReference type, you can launch record pages, tabs, lists and more.