Wednesday, October 30, 2013

JQuery Tablesorter, Meet PageBlockTable

I am definitely late to the jquery party.  In the last year or so, I've been able to harness jquery to make pages more usable and functional and just finished a poc for another beautiful jquery solution for a recurring visualforce requirement: sortable tables.

A colleague and I were doing a peer review on a visualforce page he had built.  The page had a sortable pageblocktable, which he had enabled with a custom compare function he had built in his controller.  Now, I've seen all kinds of ways of doing sorting in the controller and have done some suboptimal server-side sorting, but I never really thought about trying to keep it client-side.  I figured there'd be a way with javascript but I just didn't have it in me to try to code it up.  So, I poked around the google and sure enough, there's a jquery plugin already built to do it.  And, sure enough, another Salesforce developer, shared her solution using the tablesorter plugin years ago.

So, a few years late to the party :)

Anyway, I wanted to share my variation since I was able to get the tablesorter to work w/ the standard apex component pageblocktable.  Again, with jquery, the solution is basically the following:

1. Import your library as a static resource
2. Reference your resource in your vf page
3. Bind your jquery function and your component

So, applying the parts to my poc, I have a page that looks like this:

*******

<apex:page standardController="Opportunity" tabStyle="Opportunity" extensions="myext" id="thepage">
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/>
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"/>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
<apex:includeScript value="{!URLFOR($Resource.tablesorter, 'jquery.tablesorter.min.js')}"/>

<script type="text/javascript">
    $j = jQuery.noConflict();    
    $j(document).ready(function () {
    $j("[id$=theaddrs]").tablesorter();

    });

  //some other unrelated js

</script>

<!-- some other visualforce stuff then the heart of the proof of concept: -->

<apex:pageBlock id="theaddrsblock">

                    <apex:pageBlockTable value="{!Addrs}" var="a" id="theaddrs" styleClass="tablesorter" headerClass="header">
                    <apex:column>
                            <apex:facet name="header">
                                <apex:outputText styleClass="header" value="{!$ObjectType.Address__c.Fields.Street__c.Label}" />
                            </apex:facet>
                            <apex:outputText value="{!a.Street__c}" />

                        </apex:column>

<!-- the other columns, closing tags, and that's it -->


******

There is nothing to share about the controller because the sorting is being done w/out a callback to Salesforce.

The sections highlighted in yellow show how little is needed to modify your standard pageblocktable into a sortable table.  Not much, right?

I suggest looking at the documentation or online discussions about optional parameters that can be specified in the tablesorter library but if you just have a few fields in a table that you need to sort, the tool will do a great job of figuring out the data magically.  It's really awesome.

Now, this is only a proof of concept and so there is at least one issue resolve:  the icons to indicate sort direction are displaying on top of the column labels.  Should be able to modify the css to offset the icons.  Worst case, we just remove the styleClass attribute on the outputtext of the column facet.  Anyway, if you don't have to send it back to the controller for some logic or because the dataset is too large, just use the plugin to sort!


12 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi Micheal,

    Could you please share link to library

    Thanks

    ReplyDelete
  3. hi Raj and other readers. Sorry, I didn't think to share that very important detail! The library is called tablesorter and you can find it here: http://tablesorter.com/docs/

    ReplyDelete
  4. Thank you, this worked like charm. However I don't see the icons for sorting on table headers. Few things are redundant and can be omitted like facet header not necessarily required to be styled etc.or is it the one that adds sort icon ?

    ReplyDelete
  5. @Chirag - thanks for the feedback. Glad it worked for you. I also re-implemented this for another customer recently and did not have the sort icons either. I suspect that it has to do with the style you end up selecting. If you visit the tablesorter site, you'll see the arrows are there - I'm just not sure which style applies them. Also, agreed on the redundant tags like facet header. This was just a copy/paste issue.

    ReplyDelete
    Replies
    1. Thanks Michael for the reply! Were you able to figure out icons ?

      Delete
  6. Hi,
    It is a cool feature and thanks for sharing your experience..It is working fine with all the fields except the boolean values.
    Am getting boolean value and setting it in the table column.If the value is true column value will be a checked check box & if the value is false then it will show the unchecked check box.
    This tablesort is not working with these field.It is simply refreshing the page not sorting the values.
    Any idea....

    Thanks in advance
    Chitra

    ReplyDelete
    Replies
    1. @Chitra, yea I can see how the checkbox may not work as expected. I think text is expected by the library, so if you have some flexibility in your requirement, passing "true" or "false" or "yes" or "no" may get past the limitation. Otherwise, if you search on checkboxes and tablesorter, I'm sure you'll find a custom parser that can be added to tablesorter to extend it's capability.

      Delete
  7. It is not working for e is there a way i can put my code up and some one help me out please?

    ReplyDelete
  8. It is not working for e is there a way i can put my code up and some one help me out please?

    ReplyDelete
  9. It is not working i am not sure if i am missing something.please let me if i can get help when i post my code here

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete