function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ 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.
Melvin Smith 5Melvin Smith 5
If you need Brother Printer Support dial our toll free and get best assistance. Brother Printer Support is active all the time.
Johny SinsJohny Sins
If you are searching for reliable, quick, and budget-friendly plumbing solutions, then contact our Plumbers in Tucson (https://servicenearme.org/plumbers-in-tucson) services and get instant help 24/7.
psncode exploitpsncode exploit
Thanks for all the read this article from PSN Code Exploit (https://psncodeexploit.com/).  This is totally a valuable content