2

Is there any native Apex solution to get option to sort a column in apex data table?

0

3 Answers 3

2

If you are using apex:dataTable then you can pre-sort the data in your SOQL query. See here for an example of using apex:dataTable: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_dataTable.htm

Using the query on that page as an example, you could sort it as follows:

public List<Account> getAccounts() {
    if(accounts == null)
        accounts = [SELECT name, owner.name FROM account ORDER BY name DESC LIMIT 10];
    return accounts;
}

Notice I added the ORDER BY name DESC which will then return the results of Accounts by Name in descending order.

2

The way I've always done this is with dynamic SOQL. Start with

public String sortField = {get;set;}
public String sortDirection {get;set;}
public List<Account> tableContents {get; set;}
public String paramFromPage {get; set;}


private String queryString = 'SELECT Id, Name FROM Account';

public myController(){
    sortField = '';
    sortDirection = '';
    tableContents = Database.query(queryString + sortField + sortDirection);
}

Then the header for the <apex:dataTable/> column can be a <apex:commandLink/> that takes a parameter (like Name), assigns it to sortField, and sets the sortDirection. As in:

VF:

<apex:commandLink value="Name">
    <apex:param value="Name" assignTo="{!paramFromPage}"/>
</apex:commandLink>

APEX:

sortField = String.escapeSingleQuotes(paramFromPage); //to prevent SOQL injection
sortDirection = 'ASC NULLS LAST';

If you're interested, you can read more about SOQL injection here.

Then if they press the link in the column again, and the new sortField is the same as the old sortField, then leave it the way it is and change sortDirection to DESC NULLS FIRST and re-query for tableContents.

An added benefit of doing it this way is that you can modify the dataTable to support Field Sets without too much additional effort.

9
  • If you don't escape these sort variables, you expose an injection vulnerability.
    – Adrian Larson
    Commented Feb 7, 2017 at 19:44
  • Ah, great point. Added a note about that in my answer. Commented Feb 7, 2017 at 19:57
  • Fair enough. Trying too hard to teach a man to fish, I suppose. I left the link in there to make myself feel better, but it's part of the actual snippet now. Commented Feb 7, 2017 at 20:13
  • I'd +1 but I'm out of votes for the day.
    – Adrian Larson
    Commented Feb 7, 2017 at 20:14
  • Don't you have to give the <apex:param> tag a name attribute for it to actually bind back to the server?
    – Adrian Larson
    Commented Feb 7, 2017 at 20:19
0

The following code will show a VF page with two columns in a table :- Account ID and Account Name. Clicking on "Account Name" header in the table will cause sorting of the data in that column. If it is sorted in ascending order, then it will switch to descending order and vice-versa.

public class AccountSortHeader
{
    public List<Account> allAcc {get;set;}
    public String sortDirection {get;set;}

    public AccountSortHeader()
    {
        sortDirection = 'asc';
        String query = 'Select Id, name from Account order by Name ' + sortDirection;
        allAcc = Database.query(query);
    }

    public pageReference sortAccNamecolumn()
    {
        if(sortDirection == 'asc')
        {
            sortDirection = 'desc';
        }
        else if(sortDirection == 'desc')
        {
            sortDirection = 'asc';
        }
        String query = 'Select Id, name from Account order by Name ' + sortDirection;
        allAcc = Database.query(query);
        return null;
    }
}

VF page :-

<apex:page controller="AccountSortHeader">
  <apex:form>
    <apex:pageBlock>
      <apex:pageBlockTable value="{!allAcc}" var="a" id="AccountData">
        <apex:column headerValue="Account ID" value="{!a.Id}"/>
        <apex:column value="{!a.Name}">
          <apex:facet name="header">
          <!-- Any facet whose name is header will apply to the header of this column in the pageBlockTable -->
            <apex:outputPanel>
              <apex:commandLink value="Account Name" action="{!sortAccNamecolumn}" reRender="AccountData"/>
            </apex:outputPanel>
          </apex:facet>
        </apex:column>
      </apex:pageBlockTable>
    </apex:pageBlock>
  </apex:form>
</apex:page>

You must log in to answer this question.

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