Showing posts with label Visualforce embedded standard page refresh. Show all posts
Showing posts with label Visualforce embedded standard page refresh. Show all posts

Saturday, 7 May 2011

Refreshing Record Detail from Embedded Visualforce Page

Strange how things go in cycles.  This week there's been several questions on the discussion boards, asking how to refresh the standard record view page from an Visualforce page.  An example of an embedded page is shown below:


The purpose of the embedded page allows the user to choose a country ISO code and when the save button is clicked, populate the account billing country field with the full name of the account.

The controller method to carry out the save:

public PageReference save()
{
 Account acc=(Account) stdCtrl.getRecord();
 acc.BillingCountry=chosenCountry;
  
 return stdCtrl.save();
}


As this is an extension controller, the account is retrieved from the standard controller to update the field. The return value is the result of the standard controller save method, which is the standard record view page.

Unfortunately, as the Visualforce page is embedded in the standard view via an iframe, this simply puts the full record view page inside the existing record view page:


Not exactly what I had in mind!

Unfortunately there's no way to return a page reference to the browser that tells it to refresh the entire page, rather than just the iframe.   It is possible, however, to use javascript to carry out a client side redirect back to the record view.  Thus there needs to be some javascript that is conditionally rendered into the page after the save (and only after the save, otherwise the page will continually refresh) that executes the refresh.

The full revised controller is shown below - the new aspect is the refreshPage property, which is initialised to false in the constructor and set to true when the record is saved. I've also changed the controller to return null, as I need the embedded page to refresh and render the javascript.

public class EmbeddedController
{
 public ApexPages.StandardController stdCtrl {get; set;}
 public String chosenCountry {get; set;}
 public Boolean refreshPage {get; set;}
 
 public EmbeddedController(ApexPages.standardController std)
 {
  stdCtrl=std;
  refreshPage=false;
 }
 
 public PageReference save()
 {
  Account acc=(Account) stdCtrl.getRecord();
  acc.BillingCountry=chosenCountry;
  refreshPage=true;
  stdCtrl.save();
  
                return null;
 }
}


and the important new element in the page:

<apex:outputPanel rendered="{!refreshPage}">
   <script>
      window.top.location='/{!Account.id}';
   </script>
</apex:outputPanel>


Now when I click the save button in the embedded Visualforce page, the entire record view page refreshes and my chosen country appears in the billing address.

Update: 22/12/2012

A number of the comments for this post have asked about achieving this via the service cloud console.  This mechanism won't work I'm afraid, due to the browser same origin policy.  Looking at my javascript error console in chrome, I see 'Unsafe Javascript' exceptions when the refresh method fires.  I've also investigated converting the embedded page to a custom console component and using the integration toolkit to refresh the enclosing tab, but the same errors are thrown, event after whitelisting every domain involved.