Robust solution for tables in the visualforce page & mobile friendly.

global class jQueryDataTable_2_CTRLR {
public jQueryDataTable_2_CTRLR(){}
@RemoteAction
global static Contact getContact(){
return [SELECT Id, (Select Id from Attachments), Name, FirstName, LastName FROM Contact limit 1];
}
@RemoteAction
global static List<Account> getContacts1(){
return [SELECT Id, Sic , Name, Type, AccountNumber, AnnualRevenue, NumberOfEmployees, Ownership, Rating, YearStarted, CreatedDate, CreatedBy.Name , (Select Id, Name, Phone, MobilePhone, Email, Department, Birthdate from Contacts) FROM Account WHERE Sic <> null limit 10];
}
@RemoteAction
global static List<Account> getContacts2(){
return [SELECT Id, Sic , Name, Type, AccountNumber, AnnualRevenue, NumberOfEmployees, Ownership, Rating, YearStarted, CreatedDate, CreatedBy.Name , (Select Id, Name, Phone, MobilePhone, Email, Department, Birthdate from Contacts) FROM Account WHERE Sic <> null limit 20];
}
}
<apex:page sidebar="false" controller="jQueryDataTable_2_CTRLR">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="googlebot" content="noindex, nofollow" />
<script type="text/javascript" src="//code.jquery.com/jquery-1.12.3.min.js"></script>
<script type="text/javascript" src="//cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="//cdn.datatables.net/1.10.12/js/dataTables.bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" ></link>
<link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.12/css/dataTables.bootstrap.min.css" ></link>
<style type="text/css">
.pointer {
cursor: pointer;
}
div.dataTables_scrollBody table thead .sorting:after, div.dataTables_scrollBody table thead .sorting_asc:after, div.dataTables_scrollBody table thead .sorting_desc:after {
display: block !IMPORTANT;
}
.childTable>caption+thead>tr:first-child>td, .childTable>caption+thead>tr:first-child>th, .childTable>colgroup+thead>tr:first-child>td, .childTable>colgroup+thead>tr:first-child>th, .childTable>thead:first-child>tr:first-child>td, .childTable>thead:first-child>tr:first-child>th {
border: 1px solid #ddd !IMPORTANT;
}
.a{
color: #337ab7;
text-decoration: none;
}
</style>
<title>jQuery DataTable for SF</title>
<script type="text/javascript">
$j = jQuery.noConflict(true);
function formatChildTable(value) {
childTableHTML = '';
childTableHTML += '<table id="childTable' + value[3] + '" class="table table-striped table-bordered display childTable" cellspacing="0" width="100%" height="100%">' +
'<thead>' +
'<tr>' +
'<th>Name</th>' +
'<th>Phone</th>' +
'<th>MobilePhone</th>' +
'<th>Email</th>' +
'<th>Department</th>' +
'<th>Birthdate</th>' +
'</tr>' +
'</thead> <tbody>';
var tempArr = value[6];
for (var k = 0; k < value[6].length; k++) {
childTableHTML += '<tr>' +
'<td>' + value[6][k].Name + '</td>' +
'<td>' + value[6][k].Phone + '</td>' +
'<td>' + value[6][k].MobilePhone + '</td>' +
'<td>' + value[6][k].Email + '</td>' +
'<td>' + value[6][k].Department + '</td>' +
'<td>' + (new Date(value[6][k].Birthdate)).toLocaleDateString() + '</td>' +
'</tr>';
}
childTableHTML += '</tbody> </table>';
return childTableHTML;
}
//Dynamic Header
var firstColHeader = '';
if (true) {
//if Medical label will be as follows:
firstColHeader = 'SIC #';
} else {
//for Dental
firstColHeader = 'Column - 1';
}
$j(document)
.ready(function() {
Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.jQueryDataTable_2_CTRLR.getContacts1}',
function(result, event) {
if (event.status) {
var tableData = [];
if (result) {
for (var x = 0; x < result.length; x++) {
var temArry = [];
temArry.push(result[x].Sic ? result[x].Sic : '');
temArry.push(result[x].Name ? result[x].Name : '');
temArry.push(result[x].Type ? result[x].Type : '');
temArry.push(result[x].AccountNumber ? result[x].AccountNumber : '');
temArry.push(result[x].AnnualRevenue ? result[x].AnnualRevenue : '');
temArry.push(result[x].NumberOfEmployees ? result[x].NumberOfEmployees : '');
temArry.push(result[x].Contacts ? result[x].Contacts : '');
temArry.push(result[x].CreatedDate ? (new Date(result[x].CreatedDate))
.toLocaleDateString() : '');
temArry.push(result[x].CreatedBy.Name ? result[x].CreatedBy.Name : '');
tableData.push(temArry);
}
}
if (!$j.fn.DataTable.isDataTable('#resutTable')) {
createTable(tableData);
} else {
table.clear()
.rows.add(tableData)
.draw();
}
document.getElementById("statusMessage").style.display = "none";
}
}
);
});
var table;
function createTable(tableData) {
table = $j('#resutTable')
.DataTable({
data: tableData,
columns: [{
title: firstColHeader
},
{
title: "Name"
},
{
title: "Type"
},
{
title: "AccountNumber"
},
{
title: "AnnualRevenue",
render: $j.fn.dataTable.render.number(',', '.', 0, '$') // to show $ symbol and format the currency
},
{
title: "NumberOfEmployees"
},
{
"className": "details-control1 pointer a",
"orderable": true,
"data": null,
"title": "Contacts",
"defaultContent": "View Contacts"
},
{
title: "CreatedDate"
},
{
title: "CreatedBy Name "
}
],
responsive: true,
iDisplayLength: 5,
scrollX: true,
// "scrollY": "200px", //Height of the component
//"scrollCollapse": true, //scrollCollapse
//"paging": false, //Disabled Pagination
dom: "<'row' <'col-sm-1'><'col-sm-10' <'row'<'col-sm-6'l><'col-sm-6'f>>" +
"<'row'<'col-sm-12 pradeepDIV'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>> <'col-sm-1'>>",
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
// Bold the grade for all 'A' grade browsers
//if ( aData[4] == "A" )
// {
// $('td:eq(4)', nRow).html( '<b>A</b>' );
//}
//Coverage Issue column
if (true) //is medical
{
$j('td:eq(7)', nRow)
.html('<a href="#scrollDiv" id="' + aData[7] + '">' + aData[7] + '</a>');
} else {
$j('td:eq(7)', nRow)
.html('');
}
$j('td:eq(8)', nRow)
.html('<a href="#scrollDiv" id="' + aData[8] + '">' + aData[8] + '</a>');
}
});
// Add event listener for opening and closing details
$j('#resutTable')
.on('click', 'td.details-control1', function() {
var tr = $j(this)
.closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
this.innerText = 'View Contacts';
tr.removeClass('shown');
} else {
// Open this row
row.child(formatChildTable(row.data()))
.show();
var index = row.data();
//init the child table as same as parent table(sorting pagination and etc)
$j('#childTable' + index[3]).DataTable({
dom: "<'row' <'col-sm-1'><'col-sm-10' <'row'<'col-sm-6'l><'col-sm-6'f>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7 pull-right'p>>> <'col-sm-1'>>"
});
this.innerText = 'Hide Contacts';
tr.addClass('shown');
}
});
}
function formatChildTable2() {
document.getElementById("statusMessage1").style.display = "inline";
//Second level data change
Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.jQueryDataTable_2_CTRLR.getContacts2}',
function(result, event) {
if (event.status) {
var tableData = [];
console.log(result);
if (result) {
for (var x = 0; x < result.length; x++) {
var temArry = [];
temArry.push(result[x].Sic ? result[x].Sic : '');
temArry.push(result[x].Name ? result[x].Name : '');
temArry.push(result[x].Type ? result[x].Type : '');
temArry.push(result[x].AccountNumber ? result[x].AccountNumber : '');
temArry.push(result[x].AnnualRevenue ? result[x].AnnualRevenue : '');
temArry.push(result[x].NumberOfEmployees ? result[x].NumberOfEmployees : '');
temArry.push(result[x].Contacts ? result[x].Contacts : '');
temArry.push(result[x].CreatedDate ? (new Date(result[x].CreatedDate))
.toLocaleDateString() : '');
temArry.push(result[x].CreatedBy.Name ? result[x].CreatedBy.Name : '');
tableData.push(temArry);
}
}
if (!$j.fn.DataTable.isDataTable('#resutTable')) {
createTable(tableData);
} else {
table.clear()
.rows.add(tableData)
.draw();
}
document.getElementById("statusMessage1").style.display = "none";
}
}
);
}
</script>
<style>
.pradeepDIV{
/* width: 80%!IMPORTANT;
float: left!IMPORTANT;*/
overflow-x: auto!IMPORTANT;
}
</style>
</head>
<body>
<br/>
<br/>
<div style="text-align:center;" id="statusMessage">
<br/>
<br/>
<img src="/img/loading.gif" />
</div>
<table id="resutTable" class="table table-striped table-bordered" cellspacing="0" width="100%"></table>
<br/>
<br/>
<div style="text-align:center; display: inline;">
<button onclick="formatChildTable2(); return false;">Update Table Dynamically</button>
<div style="text-align:center; display:none;" id="statusMessage1">
<img src="/img/loading.gif" />
</div>
</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<div id="scrollDiv" >Anchor tag navigation</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</body>
</html>
</apex:page>

Comments