+ Start a Discussion
StevevStevev 

Tabbed Page Tab Focus

I'm working on a tabbed page and have set up a test control of 3 objects: Test Object A (parent object), Test Object B and Test Object C (both children of A). FYI: I did this to prevent confusing the issue with specific SF application functionality.

 

The tabbed page works fine but the default navigation is not how I would expect.

 

The scenario:  when I select a specific transaction from my list of Test Object A items it display the tabs for Test Objects A, B & C as expected. I select tab C to display the values in the Test Object C related list (OK so far). I select a row to edit a Test Object C record which is managed by a simple Apex page. Up to this point everything is working as expected. However if I save or cancel and move from the Test Object C edit page I'm returned to the tabbed page with the focus on Test Object A but I really want to be returned to Test Object C tab in focus.

 

As far as I can see there is nothing in the URL that indicates how tab focus is controlled in a tabbed page.  My guess is that the solution lies in adding code in the controller extension using "PageReference" perhaps?

 

Control of the tab focus would allow me to push a user to a specific tab based on data entered (like a wizard inside a tabbed page).

I've looked on the boards but not found any definitive solutions or suggested best practice.

 

Thanks in advance for any comments.

 

Tabbed Page:

 

<apex:page standardController="test_object_A__c" extensions="TestObjectExtension" showHeader="true" standardStylesheets="false" tabStyle="test_object_A__c"> <apex:stylesheet value="{!$Resource.Style2}"/> <apex:tabPanel switchType="client" selectedTab="tabTestObjectDetails" id="ObjectTabPanel" tabClass="activeTab" inactiveTabClass="inactiveTab" value="{!TabInFocus}"> <apex:tab label="Object A" name="test_object_A__c" id="tabTestObjectDetails"> <apex:detail relatedList="false" title="true"/> </apex:tab> <apex:tab label="Object B" name="Test_Object_B__r" id="tabObjectB"> <apex:relatedList subject="{!test_object_A__c}" list="Test_Object_B__r"/> </apex:tab> <apex:tab label="Object C" name="Test_Object_C__r" id="tabObjectC"> <apex:relatedList subject="{!test_object_A__c}" list="Test_Object_C__r"/> </apex:tab> <apex:tab label="Approvals" name="ProcessSteps" id="tabApproval"> <apex:relatedList subject="{!test_object_A__c}" list="ProcessSteps"/> </apex:tab> </apex:tabPanel></apex:page>

 Test Object C Page:

 

<apex:page standardController="test_object_C__c" id="p" extensions="TestObjectCExtension" showHeader="true" tabStyle="test_object_C__c"> <apex:form > <apex:pageBlock title="Test Object C" > <apex:pageBlockButtons location="both"> <apex:commandButton value="Save" action="{!save}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> </apex:pageBlockButtons> <apex:pageBlockSection > <apex:inputField value="{!test_object_C__c.name}"/> <apex:inputField value="{!test_object_C__c.Test_Object_A__c}"/> <apex:inputField value="{!test_object_C__c.Test_Amount__c}"/> </apex:pageBlockSection> </apex:pageBlock> </apex:form></apex:page>

 Custom Controller Extension:

 

public with sharing class TestObjectExtension { private final test_object_A__c testObj; public TestObjectExtension(ApexPages.StandardController controller) { this.testObj = (test_object_A__c)controller.getSubject(); } String tabInFocus = System.currentPageReference().getParameters().get('tab'); public String getTabInFocus() { return tabInFocus; } public void setTabInFocus( String s ) { this.tabInFocus = s; } }

 

 

 

 

 

 

 

ShikibuShikibu

Steven,

 

Your code is all mangled; Salesforce's forum software interacts badly with Safari (and perhaps other similar browsers). If you will edit your post using Firefox, you can re-post your code with formatting preserved, and will be more likely to get some help. 

ShikibuShikibu

You'll probably need some javascript. Here's some code pulled from one of my projects:

 

 

<apex:tabPanel id="CaseTabPanel"> <apex:tab label="Edit Case Details" name="detailTab" id="detailTab"> <apex:pageBlock title="Edit Case Details" mode="edit"> etc... </apex:pageBlock> </apex:tab> </apex:tabPanel> <script>var CaseTabPanel = '{!$Component.CaseTabPanel}';</script>

 

 

<script> function setActiveTab(tabName) { if (RichFaces && RichFaces.panelTabs[CaseTabPanel]) { var tabs = RichFaces.panelTabs[CaseTabPanel]; for (var i = 0; i < tabs.length; i++) { if (tabs[i].name == tabName) { RichFaces.switchTab(CaseTabPanel, tabs[i].id, tabs[i].name); break; } } } } </script>

 

And you can fetch named parameters from the URL like this:

 

 

{!$CurrentPage.parameters.my_parameter_name}

 

 

 

 

 

 

 

 

 

StevevStevev

Here is the code again but posted using Firefox (I'll have to remember for next time, thanks for the heads up!):

 

Tabbed Page:

<apex:page standardController="test_object_A__c" extensions="TestObjectExtension" showHeader="true" standardStylesheets="false" tabStyle="test_object_A__c"> <apex:pageMessages ></apex:pageMessages> <apex:stylesheet value="{!$Resource.Style2}"/> <apex:tabPanel switchType="client" selectedTab="tabTestObjectDetails" id="ObjectTabPanel" tabClass="activeTab" inactiveTabClass="inactiveTab" value="{!TabInFocus}"> <apex:tab label="Object A" name="test_object_A__c" id="tabTestObjectDetails"> <apex:detail relatedList="false" title="true"/> </apex:tab> <apex:tab label="Object B" name="Test_Object_B__r" id="tabObjectB"> <apex:relatedList subject="{!test_object_A__c}" list="Test_Object_B__r"/> </apex:tab> <apex:tab label="Object C" name="Test_Object_C__r" id="tabObjectC"> <apex:relatedList subject="{!test_object_A__c}" list="Test_Object_C__r"/> </apex:tab> <apex:tab label="Approvals" name="ProcessSteps" id="tabApproval"> <apex:relatedList subject="{!test_object_A__c}" list="ProcessSteps"/> </apex:tab> </apex:tabPanel> </apex:page>

 

Object C Page:

 

 

<apex:page standardController="test_object_C__c" id="p" extensions="TestObjectCExtension" showHeader="true" tabStyle="test_object_C__c"> <apex:pageMessages ></apex:pageMessages> <apex:form > <apex:pageBlock title="Test Object C" > <apex:pageBlockButtons location="both"> <apex:commandButton value="Save" action="{!save}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> </apex:pageBlockButtons> <apex:pageBlockSection > <apex:inputField value="{!test_object_C__c.name}"/> <apex:inputField value="{!test_object_C__c.Test_Object_A__c}"/> <apex:inputField value="{!test_object_C__c.Test_Amount__c}"/> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>

 

 Controller Extension:

 

 

public class TestObjectCExtension { public TestObjectCExtension(ApexPages.StandardController controller) { } }

 

 Not very exciting as it doesn't do anything yet.

 

 

 

sfdcfoxsfdcfox

It probably has to do with the way your page is coded; since you are embedding one page within another, your tabs are at the mercy of the inner page. When you save on the page-within-a-tab, you end up refreshing the entire page. Unfortunately, since the "selectedTab" attribute of a tabPanel is outside the form, the selectedTab attribute is lost when the page is reloaded (because it is not part of that form's view state).

I recommend that you change your Object_C__c page as follows:

 

 

<!-- old --> <apex:form > <!-- new --> <apex:form id="theForm"> <!-- old --> <apex:commandButton value="Save" action="{!save}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> <!-- new --> <apex:commandButton value="Save" action="{!save}" reRender="theForm" /> <apex:commandButton value="Cancel" action="{!cancel}" reRender="theForm" />

This will limit updates to just within the form (you would want to include a controller function to display a message advising the user that the data has been saved). Otherwise, you should consider creating a component, and using the component within the tab instead of the page. A bit more work, but probably easier to work with.

As an alternative, you could wrap the tabPanel within a form tag; that should also cause the selectedTab attribute to be preserved across page loads.

 

StevevStevev

sfdcfox,

 

Thanks for the post. I tried your suggested approach but it didn't rerender the page unfortunately (even if it worked I would prefer the be taken back to Object A in inquiry mode rather than left in edit mode). This would seem logical since the !save defaults to the standard controller and the page renders a fresh page. I have a feeling that the solution lies in using some java script as suggested in an earlier post.

 

I'm not sure how writing a component would resolve what seems to be an issue loss of tab state information. What I found interesting is that when I bring the Object C tab into focus that tab state information is clearly being held by the standard controller. I compared the URLs for when A is in focus versus C in focus and the URL does not change with a change of tab focus so it is not embedded in the URL. Once I go into Object C edit mode I suspect that the variable holding the state information is flushed and hence why I'm returned to the Object A tab on exit from the Object C update.

 

Thanks for the idea.

 

Stevev

StevevStevev

Hi Shikibu,

 

I'm trying out your suggested approach ... here is what I have so far:

 

Component:

 

<apex:component > <script> function setActiveTab(tabName) { if (RichFaces && RichFaces.panelTabs[ObjectTabPanel]) { var tabs = RichFaces.panelTabs[ObjectTabPanel]; for (var i = 0; i < tabs.length; i++) { if (tabs[i].name == tabName) { RichFaces.switchTab(ObjectTabPanel, tabs[i].id, tabs[i].name); break; } } } } </script> </apex:component>

 Just changed the naming convention to fall into my generic naming style.

 

Apex tabbed object view:

 

 

<apex:page standardController="test_object_A__c"
extensions="TestObjectExtension"
showHeader="true"
title="Object Records"
tabStyle="test_object_A__c">

<apex:pageMessages ></apex:pageMessages>

<apex:tabPanel switchType="client"
selectedTab="tabTestObjectDetails"
id="ObjectTabPanel"
tabClass="activeTab"
inactiveTabClass="inactiveTab"
value="{!TabInFocus}">

<apex:tab label="Object A" name="test_object_A__c" id="tabTestObjectDetails">
<apex:detail relatedList="false" title="true"/>
</apex:tab>

<apex:tab label="Object B" name="Test_Object_B__r" id="tabObjectB">
<apex:relatedList subject="{!test_object_A__c}" list="Test_Object_B__r"/>
</apex:tab>

<apex:tab label="Object C" name="Test_Object_C__r" id="tabObjectC">
<apex:relatedList subject="{!test_object_A__c}" list="Test_Object_C__r"/>
</apex:tab>

<apex:tab label="Approvals" name="ProcessSteps" id="tabApproval">
<apex:relatedList subject="{!test_object_A__c}" list="ProcessSteps"/>
</apex:tab>

</apex:tabPanel>
<script>var ObjectTabPanel = '{!$Component.ObjectTabPanel}';</script>
</apex:page>

Added the script to action the component highlighte in bold.

 

Controller for Tabbed Object Extension:

 

 

public with sharing class TestObjectExtension { private final test_object_A__c testObj; public TestObjectExtension(ApexPages.StandardController controller) { this.testObj = (test_object_A__c)controller.getSubject(); } String tabInFocus = System.currentPageReference().getParameters().get('tab'); public String getTabInFocus() { return tabInFocus; } public void setTabInFocus( String s ) { this.tabInFocus = s; } }

 No change made to controller yet.

 

Apex Page Test Object C:

 

 

<apex:page standardController="test_object_C__c" id="p" extensions="TestObjectCExtension" showHeader="true" tabStyle="test_object_C__c"> <apex:pageMessages ></apex:pageMessages> <apex:form > <apex:pageBlock title="Test Object C" > <apex:pageBlockButtons location="both"> <apex:commandButton value="Save" action="{!save}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> </apex:pageBlockButtons> <apex:pageBlockSection > <apex:inputField value="{!test_object_C__c.name}"/> <apex:inputField value="{!test_object_C__c.Test_Object_A__c}"/> <apex:inputField value="{!test_object_C__c.Test_Amount__c}"/> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>

 The controller extension is a place holder for now and doesn't change anything.

 

The component doesn't do anything and I think it may be due to the {!$CurrentPage.parameters.my_parameter_name}

 

I assume you suggest adding it to the TestObjectExtension but not clearhow that is supposed to work? Can you clarify?

 

Thanks

 

Stevev

 

 

 

 

 

 

 

 

 

 

raj123raj123

Hi Steve, I am also running witht hte same problem, can you give some code snppet of any idea on how did u workaround it,  it would be great help thanks,