Say you’re a web applications developer. Say you have a requirement for a grid. Say you’ve decided, like so many others, that you are not an idiot and have therefore chosen to use the “bootstrapTable” package instead of committing slow painful suicide by trying to code it all yourself. Good move!
But there are of course downsides to using packages, and a big one is that no matter how friendly the creator is, and how much customizing he offers, there’s always that one requirement you need to implement that just isn’t available. This post is about adding action buttons above the grid itself, to accompany the “Columns” and “Refresh” buttons provided.
Our simple example will consist of some common information:
- Tracking number
- Employee name
- A status, and
- Two dates
The HTML for that looks like:
<div class="col-md-10 table-responsive" style="width:auto;">
<div id="divDashboardGridResults">
<table id="tblRequestGrid" class="table table-striped table-bordered table-hover table-condensed">
</table>
</div>
</div>
and the Javascript to populate it looks like:
function initRequestGrid(initialResults) {
var gridColumnId = { field: 'TrackingId', title: '#', sortable: true, searchable: false, visible: true, align: 'left', switchable: false, formatter: buildLinkForGridId };
var gridColumnSubmitted = { field: 'SubmittedDate', title: 'Submitted', sortable: true, searchable: false, visible: true, align: 'right', switchable: true, formatter: convertJsonDate };
var gridColumnModified = { field: 'ModifiedDate', title: 'Modified', sortable: true, searchable: false, visible: true, align: 'right', switchable: true, formatter: convertJsonDate };
var gridColumnPriority = { field: 'PriorityName', title: 'Priority', sortable: true, searchable: false, visible: true, align: 'left', switchable: true, sortName: 'PriorityId' };
var gridColumnStatus = { field: 'StatusName', title: 'Status', sortable: true, searchable: false, visible: true };
var gridColumnEmployee = { field: 'Employee', title: 'Employee', sortable: true, searchable: true, visible: true };
var whichColumns = [
gridColumnId,
gridColumnEmployee,
gridColumnStatus,
gridColumnSubmitted,
gridColumnModified
];
$('#tblRequestGrid').bootstrapTable({
search: true,
showToggle: false,
showColumns: true,
showRefresh: true,
striped: true,
pagination: true,
searchAlign: 'left',
buttonsAlign: 'left',
pageSize: 20,
pageList: [10, 20, 50, 100],
columns: whichColumns,
data: initialResults,
formatShowingRows: function (pageFrom, pageTo, totalRows) {
return 'Showing ' + pageFrom + ' to ' + pageTo + ' of ' + totalRows + ' requests';
},
formatRecordsPerPage: function (pageNumber) {
return pageNumber + ' requests per page';
},
formatNoMatches: function () {
return 'No requests matched the search criteria';
}
});
The above code — fairly standard, nothing unusual — results in this:
which we are assuming is what you want, as far as the data itself is concerned. But we’ve been given some requirements from the stakeholders that
(a) the placeholder text inside the “search” input field be more verbose,
(b) that the action buttons be on the right side of the “search” input field, and
(c) that an “export” button be added in between the two built-in buttons.
Since there’s no available way to do it through bootstrapTable’s proper, we have to go behind its back by adding this code immediately after the previous Javascript lines:
// add a button next to REFRESH and COLUMN-SELECT to support exporting the table contents
var html = '';
html += '<div class="keep-open btn-group btn-group-icon-only" role="group" title="Export">';
html += ' <button class="btn btn-default dropdown-toggle btn-icon-only" data-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">';
html += ' <i class="glyphicon glyphicon-export"></i><span class="screen-reader-text-btn"> Export </span>';
html += ' <span class="caret"></span>';
html += ' </button>';
html += ' <ul class="dropdown-menu" role="menu">';
html += ' <li><a onclick="exportGrid(1);">CSV</a></li>';
html += ' <li><a onclick="exportGrid(2);">XLS</a></li>';
html += ' <li><a onclick="exportGrid(3);">DOC</a></li>';
html += ' <li><a onclick="exportGrid(4);">PDF</a></li>';
html += ' <li><a onclick="exportGrid(5);">XML</a></li>';
html += ' <li><a onclick="exportGrid(6);">PNG</a></li>';
html += ' </ul>';
html += '</div>';
// manual visual adjustments for layout/508/mobile
var $divGridToolbar = $("#divDashboardGridResults .fixed-table-toolbar");
var $divTableParent = $("#divDashboardGridResults").parent("div");
var $divGridButtons = $divGridToolbar.find(".columns");
// update display of search box
$searchInputObj = $divGridToolbar.find(".search").find("input[type='text']");
$searchInputObj.attr('placeholder', "Search on Employee and Status").attr('title', $searchInputObj.attr('placeholder'));
$divGridToolbar.prepend($searchInputObj.parent("div"));
// adjust elements manually for layout and 508
$divGridButtons.removeClass("pull-left").addClass("btn-group-icon-only").append(html);
The grid now looks like this:
And we have accomplished what we needed to do.
We didn’t have to code anything complicated or obscure, just some common-sense reverse-engineering with Firebug to determine how the existing elements were arranged and the best way to introduce our custom elements, all of it browser-independent.
What other ways have you found to add custom features to the grid? Share your wisdom with us in a comment below!
While you’re here, make yourself comfortable and check out our blog home page to explore other technologies we use on a daily basis and the fixes we’ve solved in our day to day work. To make your life even easier, subscribe to our blog to get instant updates sent straight to your inbox:
{{cta(‘33985992-7ced-4ebd-b7c8-4fcb88ae3da4’)}}