Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In a custom Visualforce page with a standard controller, how can I check and conditionally render related lists based on availability of records in the related list?

share|improve this question
is there a reason you can't use a controller extension? – Phil B Jan 23 '13 at 20:52
up vote 4 down vote accepted

Ideally one would like to write a rendered expression like so {!IF(Text__c.Test_Children_r.size > 0, TRUE, FALSE)}. However this results in an error as Visualforce is expecting a field name from the child object. Shame. So failing this, you then have two options, the first of which is preferred, as the second option, while it works is strictly speaking unsupported according to the docs.

Apex extension controller option

This example uses a controller property to expose the count. It also avoids having to perform the SOQL query itself by letting the standard controller know in advance that this information is required (typically driven by field references in the page).

public with sharing class ConditionalRelatedList 
    private ApexPages.StandardController standardController;

    public ConditionalRelatedList(ApexPages.StandardController standardController)
        this.standardController = standardController;
        this.standardController.addFields(new List<String> { 'Test_Children__r' });

    public Integer getChildCount()
        return ((Test__c) standardController.getRecord()).Test_Children__r.size();

You can then refer to the count in the rendered attribute as follows.

<apex:page standardController="Test__c" extensions="ConditionalRelatedList">
    <apex:detail relatedList="false" />
    <apex:relatedList list="Test_Children__r" rendered="{!IF(childCount > 0, TRUE, FALSE)}" />

Visualforce only option

NOTE: This option does work, but is technically unsupported, see the warnings about reassigning apex:variables within apex:repeat here.

<apex:page standardController="Test__c">
    <apex:detail relatedList="false" />
    <apex:variable var="count" value="{!0}" />
    <apex:repeat value="{!Test__c.Test_Children__r}" var="row">
        <apex:variable var="count" value="{!count+1}" />
    <apex:relatedList list="Test_Children__r" rendered="{!IF(count > 0, TRUE, FALSE)}" />
share|improve this answer
Nice answer! The second option is probably the better solution because, although the first solution does work in this case, according to the apex:variable documentation the apex:variable does not support reassignment inside of an iteration component and the result of doing so, e.g., incrementing the apex:variable as a counter, is unsupported and undefined. – Peter Knolle Jan 24 '13 at 0:15
Thanks Peter, good reference, I've updated my answer to clarify this. Thanks! – Andrew Fawcett Jan 24 '13 at 0:26
Heh, annoyed I missed this question since I used that second trick only yesterday! – LaceySnr Jan 24 '13 at 5:49
Thanks a ton. Used the second method – Ganesh Jan 24 '13 at 9:11
BTW, you can simplify your rendered attribute formula to just {!(count > 0)} instead of {!IF(count > 0, TRUE, FALSE)}. – tomlogic Feb 1 '13 at 20:49

This question prompted me to do some more research on this, and I came up with an alternative, though still unsupported, VisualForce only solution:

<apex:variable var="v" value="'{!Account.Contacts}'"/>
<apex:variable var="v2" value="'[]'"/>

<apex:outputText value="Contacts!" rendered="{!v == v2}"/>

It's a bit more concise than the apex:variable method, and doesn't involve changing the values assigned to a variable. That said, it's relying on an empty array always being represented as '[]', though I think we're on relatively safe ground with that assumption.

share|improve this answer
What is the reason behind doing your quotes like that? "'Account.Contacts'". Single quotes encased in double – EricSSH Jul 13 '15 at 15:37
It's so that instead of v being assigned an empty array value, it's assigned the string value '[]' which let's us do the comparison with v2. – LaceySnr Jul 14 '15 at 5:08

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.