Skip to content

Related List Challenges

I read an article this morning that I came across on LinkedIn as I was getting out of bed and felt that it posed some great questions and spoke to some of the challenges/frustrations users may experience regarding related lists (this also applies to standard object lists).  The article The Challenges of Loooooong Related Lists by Jennifer Laine at QueryGuru cites several issues:

  1. Difficult to Browse: Once you click on “Go To List” you will get a screen full of records. Your only option to find information is to keep clicking “Next Page”/”Previous Page” displaying more records. When there are 100s or 1000s of records it is tedious, even impractical.
  2. Impossible to Filter: There is no mechanism to limit the records to a subset of your interest. Your only option to find anything is to keep scrolling page after page after page.
  3. Fixed Display: The Related List can only display a pre-determined set of fields per the whole organization, and if you need information not found there, you may be out of luck.
  4. Cumbersome Print: Unless a Custom Button is used to invoke a Custom Report, you cannot print an ad hoc Related List. Even if a Report is used, it is tedious to customize the filters, sort order or change the displayed fields.
  5. Cumbersome Export: Exporting to Excel is very helpful in many situations. However, you have to go through a report, and even then you will end up with limited CSV file for long data sets.
  6. Reporting Challenges – both Print and Export can be achieved using Reports. However, one must assume the existence of Report Type and the inclusion of all required fields. Reports, by definition, are not designed for ad-hoc or interactive queries.

I’ve never personally developed a solution for related lists, but I have for standard list views which I think could apply here as the problems are identical.  One consideration in this regard: how many related lists can we load without blowing up salesforce and how many rows can each have?  When you’re building lists to display on a VisualForce page, the first thing I think about is View State.  On a normal VisualForce page this usually isn’t an issue, but when you need to display a list using VisualForce components you’ll notice it can get out of hand quickly.  The View State is impacted primarily by the amount of data loaded on a page and then how that data is presented.  Using VisualForce components like data tables and using an output field or output text will increase the View State with every row and column like wildfire.

For example, I’m going to using a controller to get a list of Tasks and display them in a Page Block Table.  We’ll start with 1,000 rows and 4 columns, WhoId, OwnerId, Subject and ActivityDate – which brings us to a View State of about 31k with just this simple list of the maximum 135k limit, this is only 23% so it’s not a big deal at this point.

Screen Shot 2015-03-26 at 8.18.15 AM

Screen Shot 2015-03-26 at 8.18.04 AM

 

If we add in three more columns, AccountId, Status and Priority we’ll hit about 53k (39%) with this one list of 1,000 tasks.  Let’s also remember that we don’t have any way to sort the list, paginate it, search within it or print/export it.  To accomplish all of that we’d need some serious Apex and more VisualForce controls which would expand our View State, require testing and time to deployment – not to mention the product won’t be easily modified since all Apex has to be done in a sandbox and tested.  I won’t get into all of that, instead lets get to a solution to the original question – how can we provide users an exceptional experience using lists?

For this I’m going to use jQuery, DataTables and Javascript Remoting.  DataTables will take care of all the hard work regarding sort, pagination, searching and printing/exporting (shift clicking will allow multiple column sorting also).

Screen Shot 2015-03-26 at 10.08.27 AM

Screen Shot 2015-03-26 at 10.08.31 AM

The method we’ll use to gather the data looks like this, simply pulling all Tasks in the system:


@RemoteAction
 public static list<task> getMyTasks(){

    list<task> tasks = new list<task>();

    tasks = [SELECT Id, Who.Name, Account.Name, Owner.Name, Subject, ActivityDate, Priority, Status FROM Task];

    return tasks;

 }

The Visualforce Page:

<apex:page controller="AccountTutorial" sidebar="false" showChat="false">

    <apex:includeScript value="//code.jquery.com/jquery-1.11.1.min.js"/>
    <apex:includeScript value="//cdn.datatables.net/1.10.3/js/jquery.dataTables.min.js"/>
    <apex:includeScript value="http://momentjs.com/downloads/moment.min.js"/>
    <apex:includeScript value="https://www.datatables.net/release-datatables/extensions/TableTools/js/dataTables.tableTools.js"/>
    <apex:stylesheet value="https://www.datatables.net/release-datatables/extensions/TableTools/css/dataTables.tableTools.css"/>
    <apex:stylesheet value="//cdn.datatables.net/1.10.5/css/jquery.dataTables.css"/>

    <script>

        var j$ = jQuery.noConflict();

        Visualforce.remoting.timeout = 30000;

        j$(document).ready(function(){

            getTasks();             

        });

        function getTasks(){
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.AccountTutorial.getMyTasks}',
                function(result, event){
                    if(event.status){

                        var thisTable = '<table id="example" class="display" cellspacing="0" width="100%"><thead><tr><th>Related To</th><th>Account</th><th>Owner</th><th>Subject</th><th>Date</th><th>Priority</th><th>Status</th></tr></thead><tbody>'

                        if(result.length > 0){
                            for (var i = 0; i < result.length; i++) {
                                var thisTask = result[i];
                                var thisDate = moment(thisTask.ActivityDate).format('YYYY-MM-DD');

                                thisTable += '<tr><td>'+thisTask.Who.Name+'</td><td>'+thisTask.Account.Name+'</td><td>'+thisTask.Owner.Name+'</td><td>'+thisTask.Subject+'</td><td>'+thisDate+'</td><td>'+thisTask.Priority+'</td><td>'+thisTask.Status+'</td></tr>';
                            }
                            thisTable += '</tbody></table>';
                            j$('#demo').append(thisTable);
                        }

                        j$('#example').DataTable({
                            dom: 'T<"clear">lfrtip',
                            tableTools: {
                                "sSwfPath":"https://www.datatables.net/release-datatables/extensions/TableTools/swf/copy_csv_xls_pdf.swf"
                            }
                        });

                    }

                },
                {
                    escape: false
                }

            );

        }

    </script>

    <apex:form>

        <div id="demo">
        </div>

    </apex:form>

</apex:page>

I have 4,128 Tasks in this Dev Org, all loaded up we’re at 1.48k View State!  Here’s a preview https://btspark-developer-edition.na24.force.com/taskdatatable.  There’s a lot more that can be done with DataTables in terms of functionality and design, this is just an out of the box solution – pretty simple!  It’s pretty quick to add multiple tables like this into a standard VisualForce page as related lists, putting them into a tabbed list would work nicely.

Screen Shot 2015-03-26 at 11.07.59 AM

Published inApexJavascriptjQueryVisualforce

Be First to Comment

Leave a Reply