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
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;
}
}
Great post Sam. Features like sort add to the usability of any app.
ReplyDeletegr8 post .. awsome .. thats what exactly I wa slooking for ... :)
ReplyDeleteI 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 ...
:)
I am happy that it worked well for you.
ReplyDeleteCheers,
Sam
thank you for your good solution.
ReplyDeleteIt is very helpful to me.
thanks~
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.
ReplyDeletethis 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.
ReplyDeleteI also have multiple pages/list where I need to use sorting.
Great article, i was looking for something like this for ages.
ReplyDeletethanks
Sam, what about just having the data in a related list sorted the way you want? e.g. case comments sorted newest-to-oldest?
ReplyDeletehey Sam I need help on this i have used it to display child records and sort them. here is wat i have done.everythng comes well but it doesnt sort when i click it juss the same values.
ReplyDelete{!a.Name}
------------------------------
public class PageBlockTableSortingCon {
transient private List con;
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 getCollectorNotes() {
return con;
}
public PageReference ViewData() {
//build the full sort expression
string sortFullExp = sortExpression + ' ' + sortDirection;
//query the database based on the sort expression
con = Database.query('Select id,Account__c,Collector__c,Dealer_ID__c,Follow_Up_Date__c,Note_Type__c,Peoplesoft_ID__c,Description__c, Name from Collector_s_Notes__c order by ' + sortFullExp + ' limit 1000');
return null;
}
}
how to achive both paging and sorting at the same time
ReplyDeletei am not getting what is value here ? is that a keyword ..or a property ..it is not declared anywhere?
ReplyDeleteHi SAM, this it's very helpful to me, thx
ReplyDeleteBut, I'm pretty new and I don't understand well this part, can you explain this please??
/apex:param value="name" name="column" assignTo="{!sortExpression}"/
Why are you using the var "sortExpression" in this part?
thanks for all
Hi SAM, this it's very helpful to me, thx
ReplyDeleteBut, I'm pretty new and I don't understand well this part, can you explain this please??
/apex:param value="name" name="column" assignTo="{!sortExpression}"/
Why are you using the var "sortExpression" in this part?
thanks for all
Hi Sam, Your codes and knowledge are Excellent.
ReplyDeleteSam Sir your Solutions are best.
ReplyDeleteThanks Sam, sorting helped me.
ReplyDeleteHi Sam! I was able to do this but when I clicked the arrows, nothing happens.. Please help.. Thanks!
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi Sam! I ran your code for my Object but it is giving me error "You may specify either a ''value'' attribute or a body for the column component, but not both"
ReplyDeletePl. help me out, its urgent.
Trying copy and paste the code but not able to get result facing error problem
ReplyDeleteThanks for the post.
ReplyDeleteDo you know why during sorting it is always putting blank values at the top and then sorting.
can any one help me, i need the standard controller page- block table
ReplyDeleteactions (First,Previous,Next,Last) in custom controller page -block table.
mail to sf.harsha@gmail.com if any code there--
Thanks in Advance
Thanks Sam! That was a nice workaround for table sorting and indeed very helpful.
ReplyDeleteGetting this Save error:
ReplyDeleteYou may specify either a ''value'' attribute or a body for the column component, but not both
Hi Sam,
ReplyDeleteThanks for the post. It's very helpful but is their any fast way to sort large number of records??