+ Start a Discussion
maxoutmaxout 

Nested table using apex:pageBlockTable, possible?

Hi, is it possible to create nested table on apex page using  pageBlockTable or other tags?

 

I got an erreor: Save error: Object type not accessible. Please check permissions and make sure the object is not in development mode: SOQL statements cannot query aggregate relationships more than 1 level away from the root entity object. RequestAsPDF.page.

 

Using <apex:column breakbefore> and a controller extention could fill the child table content in a new row.

But is there anything already there to use? Thanks.

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

You can not do this:

 

 

<apex:page standardController="Account">
    <apex:pageBlock>
        <apex:pageBlockTable value="{!Account.Contacts}" var="theContact">
            <apex:column>
                {!theContact.FirstName} {!theContact.LastName}
            </apex:column>
            <apex:column>
                <apex:pageBlock>
                    <apex:pageBlockTable value="{!theContact.ActivityHistories}" var="theActivity">
                        {!theActivity.Subject}
                    </apex:pageBlockTable>
                </apex:pageBlock>
            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

When the page is compiled, it generates a SOQL query that looks like this:

 

 

SELECT Id,
  (SELECT Id,FirstName,LastName,
    (SELECT Id,Subject FROM ActivityHistories)
   FROM Contacts)
FROM Account

This isn't a legal syntax (you can't query more than one level down). Instead, you need to query the data in a controller or extension and then expose the data that way.

 

Edit: Clarification. The point here is that you can't use something that will be dynamically generating a query in this case. Ideally, you'd do something like this:

 

 

public class account_wrapper {
  public account record { get; set; }
  public list<contact_wrapper> contacts { get; set; }
}

public class contact_wrapper {
  public contact record { get; set; }
  public list<activity_wrapper> activities { get; set; }
}

public class activity_wrapper {
  public activityhistory record { get; set; }
}

 

Elsewhere in your controller, call the necessary recursive queries to get all the data you need to populate this structure.

 

Finally, in your VF page, you can nest the tags recursively, as what you were originally trying to do; the syntax will be slightly different, obviously, because now you have a class that wraps the values in a way that can be fed to the pageBlockTable tag.

All Answers

sfdcfoxsfdcfox

You can not do this:

 

 

<apex:page standardController="Account">
    <apex:pageBlock>
        <apex:pageBlockTable value="{!Account.Contacts}" var="theContact">
            <apex:column>
                {!theContact.FirstName} {!theContact.LastName}
            </apex:column>
            <apex:column>
                <apex:pageBlock>
                    <apex:pageBlockTable value="{!theContact.ActivityHistories}" var="theActivity">
                        {!theActivity.Subject}
                    </apex:pageBlockTable>
                </apex:pageBlock>
            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

When the page is compiled, it generates a SOQL query that looks like this:

 

 

SELECT Id,
  (SELECT Id,FirstName,LastName,
    (SELECT Id,Subject FROM ActivityHistories)
   FROM Contacts)
FROM Account

This isn't a legal syntax (you can't query more than one level down). Instead, you need to query the data in a controller or extension and then expose the data that way.

 

Edit: Clarification. The point here is that you can't use something that will be dynamically generating a query in this case. Ideally, you'd do something like this:

 

 

public class account_wrapper {
  public account record { get; set; }
  public list<contact_wrapper> contacts { get; set; }
}

public class contact_wrapper {
  public contact record { get; set; }
  public list<activity_wrapper> activities { get; set; }
}

public class activity_wrapper {
  public activityhistory record { get; set; }
}

 

Elsewhere in your controller, call the necessary recursive queries to get all the data you need to populate this structure.

 

Finally, in your VF page, you can nest the tags recursively, as what you were originally trying to do; the syntax will be slightly different, obviously, because now you have a class that wraps the values in a way that can be fed to the pageBlockTable tag.

This was selected as the best answer
Gourav GandhiGourav Gandhi
@sfdcfox Can you please tell how can it be done dynamically such that "ActivityHistories" can be get from controller itself.