Visualforce Page embedded in a detail page that needs to redirect to other page
Asked Answered
C

3

15

I have a Visualforce page that is embedded on the detail page of Opportunities.

Within the page is a command button that invokes a method in the backing controller extension.

Once the backing method is complete, how can I redirect the user to another page?

I can return a PageReference from the method but it will only redirect the iframe that the embedded Visualforce page is displayed in.

Ideally I'd like to refresh the top level window but I'm concerned there may be cross domain issues if the embedded visualforce page isn't in the same domain as the parent window.


As a basic test in I tried adding the following to the embedded Visualforce page:

<script>
    window.setTimeout(testRedirect,2000);
    function testRedirect() {
        top.location.reload();
    }
</script>

This resulted in Chrome logging the error:

Unsafe JavaScript attempt to access frame with URL https://na2.salesforce.com/006400000000000 from frame with URL https://ab2.na2.visual.force.com/servlet/servlet.Integration?lid=066400000000000&ic=1. Domains, protocols and ports must match.

So the domains differ for the Visualforce page.

Creolized answered 19/7, 2012 at 0:53 Comment(2)
I'm looking to use this as part of the solution for my CSRF safe Custom button linked to Apex method question. It may be I need to use an apex:actionFunction with some javascript to change window.top.location.href on completion.Creolized
Hi Daniel, unless anybody has some super sneaky tactics I think you'll be out of luck with this — the problem is that the embedded visualforce pages are served up from a different domain, and so you're subject to the browser's XSS protection. Hope somebody proves me wrong and finds a way to make this work for you!Halfblood
P
16

It's a bit more code, but this works for me in all browsers, and I'm not getting any kind of cross-domain error.

Controller Extension:

public class Opp_Ext {
    private ApexPages.StandardController stdController;
    public String redirectUrl {public get; private set;}
    public Boolean shouldRedirect {public get; private set;}

    public Opp_Ext(ApexPages.StandardController stdController) {
        this.stdController = stdController;
        shouldRedirect = false;
    }

    public PageReference doStuffAndRedirect() {
        shouldRedirect = true;
        redirectUrl = stdController.view().getUrl();
        return null;
    }
}

VF Page:

<apex:page standardController="Opportunity" extensions="Opp_Ext" >
    <apex:form >
        <apex:commandButton value="Do Stuff" action="{!doStuffAndRedirect}" rerender="redirectPanel" />
        <apex:outputPanel id="redirectPanel" >
            <apex:outputText rendered="{!shouldRedirect}">
                <script type="text/javascript">
                    window.top.location.href = '{!redirectUrl}';
                </script>
            </apex:outputText>
        </apex:outputPanel>
    </apex:form>
</apex:page>
Panama answered 19/7, 2012 at 12:41 Comment(4)
Great, thanks. I guess the key point is that assigning to window.top.location.href is allowed across domains. Then it is just a matter of rendering the correct Javascript after the button is pressed. I did end up with something similar to this, but yours is better with the javascript only being sent to the client after the button press.Creolized
I've come back around to this and came up with a similar solution if the URL to redirect to is known before hand. See PageReference from embedded Visualforce page becomes inlinedCreolized
I know the stackoverflow community looks down on things like this but... thank you! Works great.Unmixed
I want to note that if you want to save the record before reloading, just add a "stdController.save();" as the first line in doStuffAndRedirect.Tipster
S
0

Try by using PageReference Class

In addition setRedirect will be useful

Sample:

public class mySecondController {
Account account;

public Account getAccount() {
    if(account == null) account = new Account();
    return account;
}

public PageReference save() {
    // Add the account to the database.  

    insert account;
    // Send the user to the detail page for the new account. 

    PageReference acctPage = new ApexPages.StandardController(account).view();
    acctPage.setRedirect(true);
    return acctPage;
}

}

Schorl answered 19/7, 2012 at 12:31 Comment(2)
I was thinking this originally, but it just loads the Opportunity page layout within the mini iframe that the VF page is embedded in.Panama
Set the target of the commandLink/commandButton to "_top" and it will load the page in the top frame, i.e. the full window.Nodule
H
-1

You need to use oncomplete = "window.top.location.href = '{!'/'+obj.id}';"

Hoffert answered 4/1, 2017 at 19:43 Comment(1)
Please provide more of an explanation how and where to use. code only answers are frowned upon, for example, someone reading through answers can't quickly figure out exactly what your fix is doing or how to use it.Reclinate

© 2022 - 2024 — McMap. All rights reserved.