Wednesday, November 12, 2008

Adding Sorting Capability to PageBlockTable Component

In one of my previous posts I demonstrated how to add paging feature to your Visualforce Pages, in this article we will explore how we can add sorting option to the PageBlockTable component.

Challenges:
  • How to replace standard header text with a link that calls a controller method for sorting the data
  • How to implement the link in such a way to support sort direction Ascending and Descending features
  • How to view Ascending and Descending state of the columns
And this is one way of meeting the above challenges:
I first replace the standard header of the Column tag with a facet tag to include a commandLink component in it.

Then I select the column name to be pasted as parameter to the controller once the commandLink header is clicked on.

Then I add some condition to the Label of header to show "Ascending" and "Descending" icons.



<apex:page controller="PageBlockTableSortingCon" tabStyle="Account">
<apex:sectionHeader title="Accounts List with Sorting"></apex:sectionHeader>
<apex:form >
<apex:pageBlock title="" id="pageBlock">
<apex:pageBlockButtons location="top">
<apex:commandButton value="View" action="{!ViewData}" id="theButton" rerender="pageBlock"></apex:commandButton>
</apex:pageBlockButtons>
<apex:pageMessages ></apex:pageMessages>
<apex:pageBlockTable value="{!accounts}" var="a" rendered="{!NOT(ISNULL(accounts))}">
<apex:column>
<apex:facet name="header">
<apex:commandLink action="{!ViewData}" value="Account Name{!IF(sortExpression=='name',IF(sortDirection='ASC','▼','▲'),'')}" id="cmdSort">
<apex:param value="name" name="column" assignTo="{!sortExpression}" ></apex:param>
</apex:commandLink>
</apex:facet>
<apex:outputLink value="/{!a.Id}" target="_blank">{!a.Name}</apex:outputLink>
</apex:column>
<apex:column value="{!a.Phone}">
<apex:facet name="header">
<apex:commandLink action="{!ViewData}" value="Phone{!IF(sortExpression=='Phone',IF(sortDirection='ASC','▼','▲'),'')}">
<apex:param value="Phone" name="column" assignTo="{!sortExpression}" ></apex:param>
</apex:commandLink>
</apex:facet>
</apex:column>
<apex:column value="{!a.BillingCity}">
<apex:facet name="header">
<apex:commandLink action="{!ViewData}" value="Billing City{!IF(sortExpression=='BillingCity',IF(sortDirection='ASC','▼','▲'),'')}">
<apex:param value="BillingCity" name="column" assignTo="{!sortExpression}" ></apex:param>
</apex:commandLink>
</apex:facet>
</apex:column>
<apex:column value="{!a.BillingCountry}">
<apex:facet name="header">
<apex:commandLink action="{!ViewData}" value="Billing Country{!IF(sortExpression=='BillingCountry',IF(sortDirection='ASC','▼','▲'),'')}">
<apex:param value="BillingCountry" name="column" assignTo="{!sortExpression}" ></apex:param>
</apex:commandLink>
</apex:facet>
</apex:column>

</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>





And this how the controller look like:




public class PageBlockTableSortingCon {

private List<Account> accounts;
private String sortDirection = 'ASC';
private String sortExp = 'name';

public String sortExpression
{
get
{
return sortExp;
}
set
{
//if the column is clicked on then switch between Ascending and Descending modes
if (value == sortExp)
sortDirection = (sortDirection == 'ASC')? 'DESC' : 'ASC';
else
sortDirection = 'ASC';
sortExp = value;
}
}

public String getSortDirection()
{
//if not column is selected
if (sortExpression == null || sortExpression == '')
return 'ASC';
else
return sortDirection;
}

public void setSortDirection(String value)
{
sortDirection = value;
}

public List<Account> getAccounts() {
return accounts;
}


public PageReference ViewData() {
//build the full sort expression
string sortFullExp = sortExpression + ' ' + sortDirection;

//query the database based on the sort expression
accounts = Database.query('Select id, Name, BillingCity, BillingCountry, Phone from Account order by ' + sortFullExp + ' limit 1000');
return null;
}

}



6 comments:

Jeff Grosse said...

Great post Sam. Features like sort add to the usability of any app.

Varun said...

gr8 post .. awsome .. thats what exactly I wa slooking for ... :)

I made slight simple modification by adding this parameter to Header Command Links :
reRender="pageBlock"

so as to make Sorting AJAX enabled .. instead of Full page refresh ...

:)

Sam Arjmandi said...

I am happy that it worked well for you.
Cheers,
Sam

yibong said...

thank you for your good solution.
It is very helpful to me.
thanks~

Jeremy Kraybill said...

Great post, thanks for the pointer! One minor note, sorting arrows usually "point" toward the "small" side of the sort, yours are pointing toward the large side of the sort. At least to match windows sorting arrow convention, they should be reversed.

Uma said...

this is a very good example. I already have a custom controller extension. How can I add another controller in my apex class to include sorting.
I also have multiple pages/list where I need to use sorting.

Post a Comment