Chuck's Code Blog

Assorted solutions and musings

Hierarchal Grid with jQuery Data Table

For anyone that may be reading this on my WordPress code blog site I wish to first apologize for the really bad code formatting in this article. I have the worse time getting code to display with correct formatting on wordpress. Perhaps someday correcting this will become a priority for me…

So I had the challenge of creating a hierarchal grid using jQuery Data Table in an MVC web application. The grid had to have the following features \ attributes and look like the mock-up image below:

  • The detail grid has been indented to indicate greater contrast from transaction rows.
  • The row with client “Brand New” has an arrow that indicates there is submission data; therefore the row can be clicked on.
  • The row with client “LiveScan1” has a ‘se’ triangle that indicates the submission data is displayed below and to the right (south east).
  • The row with client “Modified” does not have an arrow, this indicates there is no submission data; therefore the row cannot be clicked on. (on hover the cursor would not be a pointer (hand)).
 Hierarchal grid

Mock-up for hierarchal grid using jQuery Data Tables. (Click on image to enlarge it.)

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

JavaScript \ jQuery

<asp:Content ID="Content3" ContentPlaceHolderID="HeadContent" runat="server"> 
<script src="<%= Url.Content("../../Scripts/jquery.cmttooltip.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("../../Scripts/globalize.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("../../Scripts/cultures/globalize.cultures.js")%>" type="text/javascript"></script>
    <% if (false) { %>
        <link href="~/Content/WebFramework/Site.css" rel="stylesheet" type="text/css" runat="server" Visible="false" />
        <link href="~/Content/Site.css" rel="stylesheet" type="text/css" runat="server" Visible="false" />
        <link href="~/Content/WebFramework/smoothness/jquery-ui-1.8.11.custom.css" rel="stylesheet" type="text/css" runat="server" Visible="false"/>
        <link href="~/Content/WebFramework/DataTables/dataTables.custom.css" rel="stylesheet" type="text/css" runat="server" Visible="false" />
    <% } %> 
</asp:Content>   

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 

<script type="text/javascript">

/* Initialize the jQuery DataTable */ 
var oTable;           
oTable = $('#grid').dataTable({                 
"bJQueryUI": true, 
"sPaginationType": "full_numbers", 
"bFilter": true, 
"bAutoWidth": true, 
"aaSorting": [[2, 'asc']], 
"aoColumnDefs": [{ "bSortable": false, "aTargets": [0]}], 
"aoColumns": [null, null, null, null, null, null, null], 
"oLanguage": {                     
"sProcessing": "<%=.sProcessing%>", 
"sLengthMenu": "<%= Resources.sLengthMenu%>", 
"sZeroRecords": "<%= Resources.sZeroRecords%>", 
"sInfo": "<%= Resources.sInfo%>", 
"sInfoEmpty": "<%= Resources.sInfoEmpty%>", 
"sInfoFiltered": "<%= Resources.sInfoFiltered%>", 
"sInfoPostFix": "<%= Resources.sInfoPostFix%>", 
"sSearch": "<%= Resources.sSearch%>", 
"sUrl": "", 
"oPaginate": { 
"sFirst": "<%= Resources.sFirst%>", 
"sPrevious": "<%= Resources.sPrevious%>", 
"sNext": "<%=CrossMatch.StoreForward.Globalization.Resources.sNext %>", 
"sLast": "<%=CrossMatch.StoreForward.Globalization.Resources.sLast %>"
}
 }
 });
/* 'open' or 'close' an information sub-grid when a row is clicked on */ 
$('#grid tbody tr').click(function() {

              var rowstate = $(this).attr("rowstate");
              var relval = $(this).attr("rel");

              // If submissions are available, then: 
if (relval != "") {
                    var that = this;

                    // Check if row (subgrid) is marked 'closed'
                    if (rowstate == "0") {
                        // If closed, mark it 'open'; 
$(this).attr("rowstate", "1");
                        // Set the icon to show open state; 
$('#grid tbody tr >td[rel="' + relval + '"]').children().each(function(index, element) {
                            $(element).removeClass("ui-icon-carat-1-e").addClass("ui-icon-triangle-1-se");
                        });
                        // Open the subgrid here.  // oTable.fnOpen(this, fnFormatDetails(), "info_row");
                        showSubmissionsList(this);
                    } else {
// If grid is marked 'open' - mark it 'closed' 
$(this).attr("rowstate", "0");
                        // Change the row icon back to closed.
                        $('#grid tbody tr >td[rel="' + relval + '"]').children().each(function(index, element) {
                            $(element).removeClass("ui-icon-triangle-1-se").addClass("ui-icon-carat-1-e");
                        });

                        // Close the subgrid here. 
oTable.fnClose(that);
                    }
                }
                $('#subgrid tbody tr >td[rel]').cmtttooltip(
{ tooltipid: "clientdetailpopup", mouseovercallback: onmouseovercallback, mouseoutcallback: onmouseoutcallback });

            });
        });

        var submissionsByTransactionId = new Array();
        function showSubmissionsList(element) {
            var transactionId = $(element).attr('rel') + '';
            if (submissionsByTransactionId[transactionId]) {
                oTable.fnOpen(element, fnFormatDetails(submissionsByTransactionId[transactionId], transactionId), "info_row");
            } else {
                var now = Date();
                var geturl = '/Transactions/Home/Get/' + transactionId + "?now=" + now;
                $.ajax({
                    type: 'GET',
                    url: geturl,
                    success: function(submissions) {
                        if (submissions) {                           
                            submissionsByTransactionId[transactionId] = submissions;
                            oTable.fnOpen($('#grid tbody tr[rel="' + transactionId + '"]').get(0),
fnFormatDetails(submissionsByTransactionId[transactionId], transactionId), "info_row");

                        }
                    }
                });
            }
        }
        /* Function that builds the subgrid table for the row details */
        function fnFormatDetails(submissions, transactionId) {
            var sOut = '';
            sOut += '<table id="subgrid" cellspacing="0" border="1" style="padding-left:50px; margin-left:27px; padding-top:0; margin-top:0; width:98%;">';
            sOut += '<thead><tr>';
            sOut += '<th class="ui-state-default" rowspan="1" colspan="1"><span></span></th>';
            sOut += '<th class="ui-state-default" rowspan="1" colspan="1"><%= Resources.Destination %></th>';
            sOut += '<th class="ui-state-default" rowspan="1" colspan="1"><%= Resources.SubmissionStatus %></th>';
            sOut += '<th class="ui-state-default" rowspan="1" colspan="1"><%= Resources.StatusDate %></th>';
            sOut += '<th class="ui-state-default" rowspan="1" colspan="1"><%= Resources.ResponseCount %></th>';
            sOut += '</tr></thead>';
            sOut += '<tbody>';
            for (var i = 0; i < submissions.length; i++) {
                var milli = submissions[i].StatusDate.replace(/\/Date\((-?\d+)\)\//, '$1');
                var tmpdate = new Date();
                tmpdate.setTime(parseInt(milli));
                Globalize.culture("en");    // Sets culture to English (default)                
                sOut += '<tr rel="' + submissions[i].SubmissionId + '">';
                sOut += '   <td style="border-color:#D3D3D3 !important; border: 1px; border-style: solid;"  align="center" class="minimize" rel="' + submissions[i].SubmissionId + '">';
                sOut += '        <a href="javascript:void(0)" onclick="return gotopage (\'<%= Url.Action("SubmissionDetails","Home")%>/' + submissions[i].SubmissionId + '\')">';
                sOut += '            <div class="icon-edit">';
                sOut += '                <%=CrossMatch.StoreForward.Globalization.Resources.Edit%>';
                sOut += '            </div>';
                sOut += '        </a>';
                sOut += '    </td>';
                sOut += '<td style="border-color:#D3D3D3 !important; border: 1px; border-style: solid;">' + submissions[i].Destination + '</td>';
                sOut += '<td style="border-color:#D3D3D3 !important; border: 1px; border-style: solid;">' + submissions[i].Status + '</td>';
                sOut += '<td style="border-color:#D3D3D3 !important; border: 1px; border-style: solid;">' + Globalize.format(tmpdate, "d") + " " + Globalize.format(tmpdate, "T") + '</td>';
                sOut += '<td style="border-color:#D3D3D3 !important; border: 1px; border-style: solid;">' + (submissions[i].Responses ? submissions[i].Responses.length : 0) + '</td>';
                sOut += '</tr>';
            }           
            sOut += '</tbody>';
            sOut += '</table>';
            return sOut;
        };
    </script>

HTML

   <h2><%= CrossMatch.StoreForward.Globalization.Resources.Transactions %></h2>
    <%=Html.Message(Model.Message)%>
    <p></p>
        <div id="tabs-1" class="ex_highlight_row">  <%-- INBOUND --%>
            <table id="grid" style="border: 0;">    <%-- INBOUND --%>
                <thead>
                    <tr>
                        <th class="minimize"></th>
                        <th><%= Resources.TCN %></th>
                        <th><%= Resources.Name %></th>
                        <th><%= Resources.Client %></th>
                        <th><%= Resources.ORI %></th>
                        <th><%= Resources.DAI %></th>
                        <th><%= Resources.SubmissionCount %></th>
                    </tr>
                </thead>
                <tbody>
                    <% foreach (var item in Model.Transactions)
                       { %>
                        <tr rowstate="0" rel="<%= (item.Submissions.Count > 0 ? item.TransactionId : "") %>">
                            <td class="minimize, ui-state-default" rel="<%= item.TransactionId %>">
                                <%if (item.Submissions.Count > 0)
                                  { // If submissions exist for this transaction, display a row icon.
                                %><span></span><% } %>
                            </td>
                            <td><%= Html.Encode(item.TCN)%></td>
                            <td><%= Html.Encode(item.Name) %></td>
                            <td><%= Html.Encode(item.ClientName) %></td>
                            <td><%= Html.Encode(item.ORI) %></td>
                            <td><%= Html.Encode(item.DAI) %></td>
                            <td><%= Html.Encode(item.Submissions.Count.ToString()) %></td>
                        </tr>
                    <% } %>
                </tbody>
            </table>
        </div> . . .

Controller

[Authorization]
[HttpGet]
[EnforcePasswordPolicy]
public JsonResult Get(int id)
{
var submissionmodels = GetSubmissionsByTransactionId(id);
return Json(submissionmodels, JsonRequestBehavior.AllowGet);
}
Advertisements

February 16, 2012 - Posted by | jQuery, MVC

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: