34

Consider a simple example of a VF page that shows an account, with a pageBlockTable to display contacts on the account. But if there are no contacts for the accounts, instead of an empty table we want to display a message.

VisualForce Page:

<apex:page standardController="Account" extensions="AccountHelper">

  <apex:pageBlock title="Account">
      <apex:outputField value="{!account.name}"/>
  </apex:pageBlock>
  <apex:pageBlock title="Related Contacts">
      <apex:pageBlockTable value="{!contacts}" var="ct" rendered="true">
          <apex:column value="{!ct.name}"/>
          <apex:column value="{!ct.phone}"/>
      </apex:pageBlockTable>
      <apex:pageMessage summary="Account has no contacts" severity="info" rendered="true" />
  </apex:pageBlock>
</apex:page>

AccountHelper.cls:

public with sharing class AccountHelper {
    private Account account;

    public AccountHelper(ApexPages.StandardController controller) {
        account = (Account)controller.getRecord();
    }

    public List<Contact>getContacts() {
        return [select id, name, phone from Contact where accountid=:account.id];
    }
}

Note that both the 'pageBlockTable' and the 'pageMessage' in the above example include rendered='true'. What we want of course is a test of the contacts list from the controller, like this:

<!-- doesn't work, this is apex, not a formula as required -->
<apex:pageBlockTable ... rendered="contacts.size()>0">

I can't find a formula to test the list size. Is there a simple way to test this in the VF page?

One approach is to move the test to the controller, for example:

public with sharing class AccountHelper {
    private Account account;

    public List<Contact> contacts {
        get {
            if (contacts==null) {
                contacts = [select id, name, phone from Contact where accountid=:account.id];
            }
            return contacts;
        }
        set;
    }

    public AccountHelper(ApexPages.StandardController controller) {
        account = (Account)controller.getRecord();
    }

    public boolean getHasContacts() {
        return contacts.size() > 0;
    }

}

The VF page is then updated to match, e.g., rendered="{!hasContacts}. However, the list of contacts is now being cached. In a more complex example with action methods that update the database and rerender parts of the page dynamically, changes to the account's contacts in the database will not be picked up, unless we ensure each such action method also set contacts to null to ensure a fresh query. Not onerous, but our controller extension keeps adding code for what should have been a simple in-page test.

But let's take the example one step further. Let's say that we want alter the display (add an icon, or change the background color) of each contact based on whether or not the contact has any cases in the system. The query in the controller can get cases:

contacts = [select id, name, phone, (select casenumber from cases) from Contact where accountid=:account.id];

But how can the VF Page test the cases subquery to alter the display? The only approach I know of is to create an inner wrapper class for contact, and have the Contacts getter return a List of wrapper objects; the wrapper class can the have the logic to check cases. This will work, but again, the controller is growing in complexity for what is basically a simple test - does a list have members?

2 Answers 2

48

This is just a syntax issue, your condition will work if you make a few small changes

Change

 <!-- doesn't work, this is apex, not a formula as required -->
    <apex:pageBlockTable ... rendered="contacts.size()>0">

To

 <apex:pageBlockTable ... rendered="{!contacts.size>0}">
4
  • the missing {! } tags are just my mistake in typing the question, but dropping the parens from contacts.size() is the magic I was missing. Further, in my extended example, {!ct.cases.size} does exactly what I need as well. Thanks! Sep 29, 2013 at 17:09
  • Awesome, glad to help Sep 29, 2013 at 19:00
  • 3
    You can also use '.empty'
    – Phil B
    Sep 25, 2014 at 14:56
  • Good point, that will work as well. Sep 25, 2014 at 15:02
6

You can do this as:

<apex:pageBlockTable ... rendered="{!IF(contacts.size>0,'true','false')">

On visualforce page we can check conditions by:{!IF(condition,InTrueCondition,IfConditionIsFalse)}

Same as List size can be checked as:

<apex:pageBlockTable value="{!contacts}" var="ct" rendered="{!IF(contacts.size>0,'true','false')">
          <apex:column value="{!ct.name}"/>
          <apex:column value="{!ct.phone}"/>
      </apex:pageBlockTable>
      <apex:pageMessage summary="Account has no contacts" severity="info" rendered="{!IF(contacts.size>0,'false','true')" />

So by {!IF()} you can check various conditions and display results according to it. Also on VF page {!contacts.size>0} will result to true when rendered. So rendered="{!contacts.size>0}" can be used in your case.

Reference: read here

Edit: Also instead of using rendered="{!contacts.size>0}" or using {!IF()}, function {!listInstance.empty} can be used.

So in case for a empty list {!contacts.empty} will render true and {!!contacts.empty} will render false

3
  • 7
    IF(BooleanTest, 'true', 'false') is never needed - a boolean test by definition returns true when true and false when false. Likewise, NOT(BooleanTest) is cleaner and clearer than IF(BooleanTest, 'false', 'true'). In my case, the issue was the () on contacts.size(), which won't work in a VF formula. You currently show it both correctly and incorrectly (last example) in your answer. Sep 29, 2013 at 17:15
  • @JasonClark I corrected it, that was a typo mistake. Thanks! NOT(Boolean) is no doubt more cleaner. I just tried to described some of the approaches and in last line the solution.
    – Ashwani
    Sep 29, 2013 at 17:20
  • 2
    I know you edited the last line to reflect, but I think what Jason is trying to say is that there is no reason ever to use a boolean condition in an IF statement in VF. Its redundant and really just adds complexity where it isn't needed. Your answer makes it seems as though it is an effective alternative, but really there is no reason to add the IF statement Sep 29, 2013 at 20:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .