Formatting PowerShell tables with jQuery and DataTables
One of the great things about PowerShell is its ability to easily export objects to HTML, which - with a little CSS - makes it straightforward to create great-looking reports. But static lists of data aren’t enough any more, the people demand interactivity.
DataTables is a plug-in for the jQuery JavaScript library which is great for displaying interactive HTML tables, with options for sorting and filtering. You can have a look at some of the examples on their page to see how powerful it is.
Unfortunately for us, DataTables requires that HTML tables be formatted in a particular way, with the THEAD and TBODY sections declared, and this formatting is not the same as the tables output from the ConvertTo-HTML CMDlet.
For example, say we want to get a list of VMware services running on the current machine. We’re going to output the HTML table to a text file, and then use a server-side-include to integrate it into a larger page (with headings, a style sheet, navigation etc.). We can generate the HTML easily with the following command.
Get-Service -Name VMware* | Select-Object Name,Status | ConvertTo-HTML -Fragment
By looking at the output generated, we can see that, although valid HTML, it doesn’t have the THEAD and TBODY sections required by DataTables.
<table>
<colgroup>
<col/><col/>
</colgroup>
<tr><th>Name</th><th>Status</th></tr>
<tr><td>vmware-converter-agent</td><td>Running</td></tr>
<tr><td>vmware-converter-server</td><td>Running</td></tr>
<tr><td>vmware-converter-worker</td><td>Running</td></tr>
</table>
The following Javascript, added to the HEAD section of the document dynamically changes all the incorrectly formatted tables on the page, and allows them to be displayed as DataTables.
<script type="text/javascript">
$(document).ready(function(){
$('table').each(function(){
// Grab the contents of the first TR element and save them to a variable
var tHead = $(this).find('tr:first').html();
// Remove the first COLGROUP element
$(this).find('colgroup').remove();
// Remove the first TR element
$(this).find('tr:first').remove();
// Add a new THEAD element before the TBODY element, with the contents of the first TR element which we saved earlier.
$(this).find('tbody').before('<thead>' + tHead + '</thead>');
});
// Apply the DataTables jScript to all tables on the page
$('table').dataTable( {
// Put your datatable options here
});
});
</script>
It may not be the most elegant use of Javascript, as I was learning as I went along, but hopefully it might save someone else some time.