5

I'm using a VF page as a "dispatcher" to display different pages based on an object recordtype.

<!-- OverrideCaseView
     If Case is a XXXX, show in the XXXXX user interface
     Otherwise, show the normal Case page.
-->
<apex:page standardController="Case"
    action="{!IF(case.RecordType.DeveloperName='XXXXXXXXX',
                 URLFOR($Page.XXXXXXOverview, null, [id=case.Id], true),
              URLFOR($Action.Case.View, case.Id, null, true))}">
    <apex:outputPanel style="display:none;" >
        {!case.RecordType.DeveloperName}
    </apex:outputPanel>
</apex:page>

Up until now, I've just been doing View overrides, but I'm adding some edit overrides as well. When they're complex, it makes sense to have a separate dispatcher page, and I'm trying to figure out if I could re-use the same page for simple cases.

When writing a VF page to be used as a button/action override, is there any way to tell which action you're overriding? Is this information included in any parameters or global variables?

2 Answers 2

4

Visualforce Pages and Action Overrides.

Currently there is no context other than that passed in the standard controller given to you by the platform. Which really just gives you the SObject and not the action invoked apone it. However this allows your controller code to be generic at least. Allowing you to reuse a controller between different pages...

You can only associate pages to Action Functions that use standard controllers and hence the object needs to be explicitly stated on the page, preventing the pages from being reused between other objects. Context wise, you can determine your current page however. So it then becomes a question of how light you can make your Action Override pages....

Dispatch Suggestion "Using very small pages for mulitple overrides".

Create an extension controller, MyDispatchController, with a 'dispatch' method on it (returning PageReference). Then create a VF page for each action you want to override and configure the Action Override to each. As a minimum it would look like this for a Test object...

Dispatch Action Pages and Controller:

Create for example, testdispatchedit.page, testdispatchnew.page and testdispatchview.page each looking like the following...

<apex:page standardController="Test__c" extensions="MyDispatchController" action="{!dispatch}"/>

Then in the 'dispatch' method of the controller put your object and/or action dispatch logic...

public with sharing class MyDispatchController 
{
    public MyDispatchController(ApexPages.StandardController stdController) { }

    public PageReference dispatch()
    {
        if(ApexPages.currentPage().getUrl().contains('view'))
            // Some disaptching logic resulting in a PageReference 
            //   (could also reference standardController.getRecord() for object type)...
            return Page.testviewa;
        else if(ApexPages.currentPage().getUrl().contains('edit'))
            // Some disaptching logic resulting in a PageReference 
            //   (could also reference standardController.getRecord() for object type)...
            return Page.testedita;
        else if(ApexPages.currentPage().getUrl().contains('new'))
            // Some disaptching logic resulting in a PageReference 
            //   (could also reference standardController.getRecord() for object type)...
            return Page.testnewa;
        return null;    
    }
}

For the pages that you dispatch to, define these as follows...

testedita.page:

<apex:page standardController="Test__c" extensions="MyDispatchController,TestEditAController">
    Edit Page A
</apex:page>

testnewa.page:

<apex:page standardController="Test__c" extensions="MyDispatchController,TestNewAController">
    New Page A
</apex:page>

testviewa.page:

<apex:page standardController="Test__c" extensions="MyDispatchController,TestViewAController">
    View Page A
</apex:page>

VF Bindings and Standard Controller Record: Note that the standard controller record is initialised with the fields as per those referenced on the disapatch page. Which of course does not reference any fields. This means that standardController.getRecord() will really only have the Id field populated. You could resolve this by adding some bindings to the dispatch page (these won't be displayed), say for some common fields all your dispatch to pages need. So be aware that the final controllers will likely have to query themselves for the information they need and expose this to the page themselves.

Summary: This solution leverages a feature of Visualforce that allows you to share controller instances between pages. So long as they share the same controllers. This allows your final pages to also see the same instance of the MyDispatchController, should you want to store anything in that during the dispatch, that you want to reference.

Hope this helps!

3
  • Looks promising... you use e.g. ApexPages.currentPage().getUrl().contains('view') -- does that mean the override action is representing in the URL? How does it show up? I know that SFDC includes sfdc.override=1 in the URL, but hadn't seen any reference to the specific action.
    – Benj
    Commented Mar 14, 2013 at 2:32
  • 1
    No its looking for the action part of the page name, e.g. /apex/testdispatchedit or /apex/testdispatchview etc. You have to have a different page, the page used is the only context to determine the action. The approach I've shown above is to make the actual page as small as possible. The end result is you do get to implement the dispatch logic in one place as was the original requirement. Just with the need for some small pages to link to it. Commented Mar 14, 2013 at 2:48
  • Makes sense. Thanks for the additional explanation.
    – Benj
    Commented Mar 14, 2013 at 2:51
1

You configure the Visualforce override in the Standard Buttons section within the sObject that you're overriding for. There's nothing in the Visualforce page other than your own custom logic to determine switching.

The only requirement would be for any custom controllers to be an extension of the Standard sObject Controller, so that it appears in the button overrides drop down.

From a deployment standpoint, the last time I checked there was nothing in the metadata files for standard objects to indicate overrides, which meant you had to manually deploy overrides for standard objects across environments. However the overrides did show up in Custom object metadata files.

In summary you'd probably have to do a dispatch controller per type of action.

1
  • Most of this info is correct, although I don't see what it has to do with the question on hand. I think your conclusion is probably right, though.
    – Benj
    Commented Mar 13, 2013 at 19:33

You must log in to answer this question.

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