I am looking at a robust & scalable approach to include multiple (~10) VF Pages as Tabs into the Main VF Page. Each of these will have its own controllers (heterogeneous controllers overall). What approach do you recommend? What Governor Limits to Watch Out For?
-
Can you provide more detail on what you're trying to do? By "tabs" do you mean standard SFDC Visualforce tabs, or something else?– jkraybillCommented Apr 2, 2013 at 3:03
-
I am trying to include 10+ VF Pages into one main VF Page. The 10 different VF Pages will have to be included as Tabs (via apex:tab). The below approach by James exactly represents the scenario that we are trying to achieve. But as pointed out by Ralph is using <apex:include> better than the component approach as advocated by James?– KaLiCommented Apr 2, 2013 at 6:37
-
It will probably be just fine. I dislike the apex:tab component because you can't customize its behaviour much, and it's easy for the code to get out of hand (James Davies' approach below helps with this). I prefer to use jQuery UI tabs for those reasons. But anyway, no, you should not run into governor limit issues. I'm pretty sure, but not 100%, that you won't see view state bloat either - I think each tab is going to have separate view state and you won't have a huge view state by having many tabs. That would be my main worry.– jkraybillCommented Apr 2, 2013 at 6:45
-
From personal preference I consider Components cleaner, but using apex:include would likely work just as well with my answer below. I'm not 100% whether the ViewState is cumulative for governor limit purposes, but you still need to factor in page load times. Try and keep the ViewStates for each controller as small as possible, and put any shared data in a common root controller.– James DaviesCommented Apr 3, 2013 at 5:35
1 Answer
I would break each page into a VisualForce Component, and then embed each component into its own tab. You can use standard visualforce tabs (apex:tab) or a third party javascript library.
There's no major gotchas with this technique. This doesn't use any extra governor limits, however you will need to take into account that each of those ten components will run their constructors on page load, and governor limits for these will be accumulative.
For Example:
Tab1.component
<apex:component controller="Controller1">
Content Here
</apex:component>
Tab2.component
<apex:component controller="Controller2">
Content Here
</apex:component>
YourPage.page
<apex:page>
<apex:tabPanel switchType="client">
<apex:tab label="One"><c:Tab1></apex:tab>
<apex:tab label="One"><c:Tab2></apex:tab>
</apex:tabPanel>
</apex:page>
If you need to share data between components, you can instead create a root controller on the page, and use it as a factory to create constructors for the child components.
i.e.
Tab1.component
<apex:component>
<apex:attribute name="Controller" type="MyController" description="The controller to pass to this component" required="true">
<apex:inputField value="{!Controller.FirstName}"/>
</apex:component>
RootController.cls
class RootController {
public MyController getTabOneController(){
return new MyController(this);
}
}
YourPage.page
<apex:page>
<apex:tabPanel switchType="client">
<apex:tab label="One"><c:Tab1 Controller="{!TabOneController}"></apex:tab>
</apex:tabPanel>
</apex:page>
-
I can't find any hard references to it. But at the last dreamforce product managers advised that there are some known issues when loading a large number of components or including multiple sub-visualforce pages in one page. Might be worth doing some scalability checks before committing to this sort of approach fully. Commented Apr 2, 2013 at 3:25
-
Good point. I've had over 20 components on one page without issue, however they were 20 instances of the same component. Would be worthwhile making sure 20 different components on the same page works as well. Commented Apr 2, 2013 at 3:41
-
1Totally, this was an off hand comment from a PM, so I don't really have much to back it with. I think they were more focused on apex:include Commented Apr 2, 2013 at 3:47
-
1Was able to achieve the requirement using apex:include, thank you all for the rich insights...– KaLiCommented Apr 27, 2013 at 13:26