9

I'm working on a Visualforce page that (forgetting about page layouts for a moment) takes in a Record Id (from one of a variety of objects), does some querying for Content based on that Record Id, and returns a list of Content items. In terms of the actual query, it doesn't care what the Record Id is. So really I only need a single Controller to handle this query, pagination, sorting, etc.

Now back to the page layouts. I want to display these lists of Content on various page layouts, for different objects. Here the issue is that in order to display a VF page on a page layout, it needs to use the standard controller for that object. The downstream impact of that is that the VF page controllers now have to be extensions, which means I have to create an individual controller for each VF page. That doesn't scale very well.

Is this possible? Am I stuck creating individual VF pages with standard controller extension classes?

7 Answers 7

10

You don't have to create a separate apex controller for each VF page, but you do need 1 VF page per standard controller you need to "extend".

What I generally do is create a single controller class that uses generic SObject methods to manipulate its data. That controller has a method, getCtl(), which returns itself. I generify the VF content into a custom component which takes the single controller class as an argument. Then I create multiple VF pages with just a one-liner to that component, e.g.

<apex:page showHeader="false" sidebar="false" standardController="Account" extensions="MyGenericController">

    <c:MyCommonVfComponent ctl="{!ctl}" />

</apex:page>
1
  • 1
    Thanks! This is exactly what I ended up doing, apologies for the late followup. Commented Sep 11, 2012 at 16:15
5

Implement total functionality as a component and use it in the different pages.

Example: 1. Create a component which takes two parameters. one is Record id, another one is type of the record (ex: account, contact, ...)

<apex:component controller="samplecon">
<apex:attribute name="recordid" type="String" required="true"/>
<apex:attribute name="objecttype" type="String" required="true"/>
.......
logic follows here
.......
</apex:component>

2. Create object specific VF pages and include component

<apex:page standardController="objectname">
<c:customcomponent recordid={!recordid} objecttype={!objectname}/>
</apex:page>

recordid: record id passed to the page

objectname: name of the object referring

No custom controller is required unless you do something else.

1
  • Could you expand on this a bit? Maybe with a small example or a link to the functionality in question. Commented Aug 23, 2012 at 1:05
2

This is HACK and not recommended:

The only way you can save n pages and just have one page is that

  • create a controller to be SOBJECT one (as suggested by others) ie generic one
  • create a page using standardcontroller attribute and then update pagelayout of that object and include this page as inline
  • Then you can go and update the same vf page and remove the standardcontroller attribute and the inline visualforce page will still work (hoping you have coded everything as generic sobject and not hard-coded for a particular object)
  • This process you can repeat for every object ie update same vf page with the desired object name as standardcontroller and add it to that object page layout, and then remove the standardcontroller tag.

PS : This is just a hack and not at all recommended approach.

2
  • Does this actually work? Would be pretty crazy if it did... Commented May 21, 2015 at 22:21
  • It worked when I tried but as I said at top of post its HACK and not recommended :) Commented May 22, 2015 at 6:08
1

It won't fully solve your scaling issue, but could you make the core controller an abstract base class and then only extend it as required for each specific object?

See Inheritance and Visualforce page controllers

1

The only reason a controller is considered an extension controller is if it has a constructor of the form:

public MyController(ApexPages.StandardController std)

Thus your single controller can be used as an extension for any standard object. You can then access the id of the standard object via the standard controller getId method.

public MyController(ApexPages.StandardController std)
{
   Id recId=std.getId();
}

However, if all you want is the record id to use in some custom apex, I'd suggest using a custom component with its own controller, and simply passing in the record id as an attribute. That way you can do away with an extension controller and each of your Visualforce pages is reduced to:

<apex:page standardController="Account">
   <c:MyComponent recId="{!$CurrentPage.parameters.id} />
</apex:page>

You do still need a page per standard object though, in order to be able to embed them in the view.

0

You can implement a VF page and as long as it shares the standard controller of the object whose page layout your trying to add it too, it's available to be added to that page in the standard page-layout controller.

0

If you can, invert your problem so that you have a VF page that displays your object details and whatever else you want. Check out the <apex:detail> tag.

You must log in to answer this question.

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