[SalesForce] How to create tabs for an apex:tabPanel dynamically with apex:repeat and rerender

I have an inputfield in my form which is a lookup. When I select a record from the list of lookup records (clicking the small magnifying glass) I am reading the id of that record and querying the related fields in my controller.

This is the lookup inputfield

   <apex:inputField value="{!account}" onchange="getAccountId(this);"/>

In my script

  var getAccountId = function(e) {
        var id = document.getElementById(e.id + '_lkid').value;
        getRelatedAccountHolders(id);
    }

<apex:actionFunction name="getRelatedAccountHolders" action="{!getRelatedAccountHolders}" rerender="accHolderTab">
  <apex:param name="accId" value=""/>
</apex:actionFunction>

In my controller

public List<AccountHolder__c> accHolderList {get; set;}
public void getRelatedAccountHolders() {
     Id accountId = ApexPages.currentPage().getParameters().get('accId');
     accHolderList = [select name, age, email from AccountHolder__c where Account = :accountId];
}

Now in the form there is a tabPanel which is suppose to show the account holders. I am planning to populate the tabs using repeat, something like this

 <apex:tabPanel id="accHolderTab">
      <apex:repeat value="{!accHolderList}" var="accHolder">
           <apex:tab label="lab" name="accHolder.Name">
                 <apex:outputPanel >
                            //display account holder info in elegant form
                 </apex:outputPanel>
             </apex:tab>
       </apex:repeat>
</apex:tabPanel>

I am getting the list of account holders in accHolderList but the tabPanel does not get rendered or populated (I see an empty space and no tabs or panel at all).

I think that the tabPanel is rendered before the query is made in the controller and since the accHolderList is null at that time, it does not render anything.

Am I doing this right? Is there any other way to render AccountHolder records onchange of the Account lookup inputfield?

Thanks.

Best Answer

Unfortunately you can't use the apex:tabPanel with the apex:repeat as you tried:

apex:repeat

This component can't be used as a direct child of the following components:

<apex:panelBar>
<apex:selectCheckboxes>
<apex:selectList>
<apex:selectRadio>
<apex:tabPanel>

Based on this, you can use tabPanel only in non-dynamic scenarios, where you can create at least all the tabs statically without apex:repeat

As a workaround you could look for an alternate tab-component like

As long as you can create the markup inside the repeater or as a full javasrcipt string, which can be executed, you should be good to go.

By the way I found lots of conceptual errors in the code provided in you question. My testcode was in the end:

TestPage.page

<apex:page controller="TestPageCtr">
    <apex:form>
        <apex:inputField value="{!ah.Account__c}" onchange="getAccountId(this);"/>  
        <script>    
            var getAccountId = function(e) {
                var id = document.getElementById(e.id + '_lkid').value;
                getRelatedAccountHolders(id);
            }
        </script>
        <apex:actionFunction name="getRelatedAccountHolders" action="{!getRelatedAccountHolders}" rerender="wrapper">
            <apex:param name="accId"  assignTo="{!accId}" value=""/>
        </apex:actionFunction>
        <br/><br/>
        <apex:outputPanel id="wrapper">
            <apex:outputText value="{!accId}"></apex:outputText>
            <br/><br/>
            <apex:repeat value="{!accHolderList}" var="accHolder">
                <apex:outputText value="{!accHolder.name}"></apex:outputText><br/>  
            </apex:repeat>
            <apex:tabPanel switchType="client" id="theTabPanel1">
                <apex:repeat value="{!accHolderList}" var="accHolder">
                    <apex:tab label="{!accHolder.Name}"  >
                        <apex:outputText value="{!accHolder.name}"></apex:outputText><br/>
                    </apex:tab>
                </apex:repeat>
            </apex:tabPanel>
            <apex:tabPanel switchType="client" id="theTabPanel2">
                <apex:tab label="LAB">
                    <apex:outputText value="TEST fgsdfg sdfgsdfg sdfg s"></apex:outputText><br/>
                </apex:tab>
                <apex:tab label="LAB2">
                    <apex:outputText value="TEST sf 4444 "></apex:outputText><br/>
                </apex:tab>
            </apex:tabPanel>
        </apex:outputPanel>
    </apex:form>
</apex:page>

TestPageCtr.cls

public class TestPageCtr {
    public AccountHolder__c     ah                                      { get; set; }
    public string               accId                                   { get; set; }
    public TestPageCtr() {
        this.ah = new AccountHolder__c();
        getRelatedAccountHolders();
    }
    public List<AccountHolder__c> accHolderList {get; set;}
    public PageReference getRelatedAccountHolders() {
         accHolderList = [select name, age__c, email__c from AccountHolder__c where Account__c = :accId];
         return null;
    }   
}

Conclusion

  • theTabPanel2 works always as expected
  • theTabPanel1 stays empty forever ==> not apex:tab inside apex:repeat