We have been building data tables for ages, and much of the elements are the same, such as fetching data from the server, presenting them on a table, being able to search, sort, etc.. Today we'll gather all these into a simple page using Tabular and Ruby on Rails for the server side. Rails is not really important here and we could have used any backend web framework.
Setup
Tabular needs jQuery so we make sure we have that included on our page. Then we grab the JavaScript file from Tabular's Github repo and save it on the /vendor/assets/javascripts
folder of our Rails app, or whatever folder you put your JavaScript files if you don't use Rails.
We then grab the minimal Tabular CSS file and add it to the /vendor/assets/stylesheets
folder (or your folder of choice). In Rails we need to reference the files into our application.js
and application.css
files respectively.
The Model
Since we're showing a table of users, we have a User model with the following attributes, that will be shown on the table.
id
name
email
company
salary
We have populated the users table with some fake data using the awsome ffaker gem. We've ended up with around 200 users, in order to see the pagination working.
The Controller
In a simple UsersController
controller we have an index
action that looks like this:
# app/controllers/users_controller
class UsersController < ApplicationController
def index
@page_size = (params[:page_size] || 10).to_i
@users = User.page(params[:page]).per(@page_size)
if params[:sort].present?
@users = @users.order(params[:sort][:name] => params[:sort][:dir])
end
if params[:q].present?
@users = @users.where('LOWER(name) LIKE ?', "%#{params[:q]}%")
end
end
end
We have used the kaminari gem for pagination. Please note the parameters that work with Tabular:
page_size
- provides the number of rows per page, by default one of 10, 25, 50; we can also specify our own variantspage
- provides the number of the current page; it could benil
.sort[:name]
- the name of the column we're sorting bysort[:dir]
- the direction of sortingq
- the search term
As we can see, we have full control on pagination, sorting, and searching on the back end and we can apply them as we wish.
The Views
Tabular accepts the data in JSON format, so we build the index view with JBuilder:
# app/views/users/index.json.jbuilder
json.metadata do
json.current_page @users.current_page
json.total_pages @users.total_pages
json.total_entries @users.total_count
json.page_size @page_size
end
json.data do
json.array! @users
end
Tabular's data format is built of two parts:
metadata
:Object
- provides information about the datadata
:Object[] Array
- the actual data
The metadata includes information such as:
current_page
- the number of the current pagetotal_pages
- the total number of pagestotal_entries
- the total number of rowspage_size
- the number of rows currently shown on a page, initially provided by Tabular
The data is provided as an array of User objects, created in a user
partial:
json.extract! user, :id, :name, :email, :company
json.salary number_to_currency(user.salary)
json.show_link link_to('View', user_path(user), class: 'tabular-btn')
Here we extract the data we need from the User, including the salary formatted as currency. Tabular also accepts HTML markup, so we include a link to the user details. The tabular-btn
class is provided by Tabular and we'll see the styles a bit later.
Setup
Not it's time to instantiate Tabular, and we'll do this on the app/views/users/index.html.erb
page:
<h1>Users</h1>
<div id="tabular" class="tabular-demo"></div>
<script>
$(function() {
tabular.start('#tabular', {
columns: [
{ title: 'Id', name: 'id' },
{ title: 'Name', name: 'name' },
{ title: 'Email', name: 'email' },
{ title: 'Company', name: 'company' },
{ title: 'Salary', name: 'salary' },
{ title: '', name: 'show_link', sort: false }
],
source: '/users.json'
});
});
</script>
Tabular can be instantiated by calling tabular.start
function with the table container and some options (more info at Tabular page).
The columns
options accept an array of object options for each table column:
title
- the text to show on the headingsname
- name of the data attribute in JSON response from the serversort
- tells Tabular to use sorting for this column.
The source
specifies the link to server data.
Styles
Tabular is not opinionated about styles, it lets most of the bulk of it to us users, so that we can inject our own custom or framework styles, such as Bootstrap or Foundation. Tabular does come with a small CSS file that we already included on our page, outligning the basic layout of its plugin elements.
We're going to add our own styles though, taking advantage of the CSS classes assigned to different elements by Tabular.
.tabular-demo {
.tabular-btn {
background: #ceeffb;
border: none;
border-radius: 2px;
font-size: .8em;
color: #598da0;
cursor: pointer;
display: inline-block;
padding: .2em .4em;
&:hover {
background: #a8dff3;
}
&[disabled] {
color: #86daf6;
cursor: default;
&:hover {
background: #ceeffb;
}
}
}
.tabular-paginator select {
height: 1.8em;
}
.tabular-paginator-info {
font-size: .8em;
}
.tabular-header {
margin-bottom: 1em;
}
.tabular-search {
float: right;
input {
font-size: .8em;
padding: .2em .3em;
border: 1px solid #ddd;
border-radius: 2px;
}
}
th,
td {
font-size: .8em;
padding: .2em;
border-bottom: 1px solid #eee;
&:last-child {
text-align: right;
}
}
th {
border-top: 2px solid #eee;
border-bottom-width: 2px;
a {
text-transform: uppercase;
font-size: .8em;
}
}
.tabular-sort {
padding-right: 1.5em;
}
}
Here we style the buttons, the table headings and cells to achieve a layout as in the demo page. You may extend the styles as it fits the needs of your web app.
Conclusion
In the demo page you may see click on the headings to test how sorting works, check the pages dropdown, etc.. This is a small example on how to tabulate data on a web app, without reinventing the wheel about searching, sorting, pagination, loading data, etc..