/LittleBigTable

A lightweight interactive AlpineJS html table

Primary LanguageJavaScriptMIT LicenseMIT

littleBIGtable

littleBIGtable is a small (~5k gzipped) javascript table built using AlpineJS

Screenshot

See the Complete example in action, this uses Bulma for the styling as shown above.

littleBIGtable is very new and while it works well for my purposes you may find issues, please report them in the issue tracker.

littleBIGtable is CSS agnostic and can be used with any css framework, the default examples use Bulma, there is also a Bootstrap example using Bootstrap 4 and a Basic example with no css. I imagine it would be great with TailwindCSS too.

As you have complete control over the HTML you can structure and style it however you wish.

Goals

  • Allow you the developer to completely control the look and feel of the table by wrapping a standard HTML table in an AlpineJS component.
  • Make the viewing and searching of large remote datasets easy, it does not use local data, it only fetches data from your chosen endpoint.

Why

I created this as too many table plugins render the table in an opinionated fashion, I wanted to be able to write the table in HTML and 'sprinkle' the javascript over it to make it interactive.

Changelog

[0.1.0] - 2021-02-12

First dependable release, I have started using this in Production.

Added

  • New setting headers to allow sending custom HTTP headers with the requests.
  • New setting args to allow setting the url query argument names to suit your application.

Changed

  • The default storage key prefix is now capitalised to match the new project name, it was 'lbt' now it is 'lBt', hopefully this makes it more obvious as to what it relates to.

Fixed

  • An issue with the pager display when the total number of results was less than number of results to show

Installation

Using the CDN

Link to the main javascript file

<script src="https://unpkg.com/littlebigtable@0.1.1/dist/littleBIGtable.min.js"></script>

If you want to use the supplied icons you must refer to them when passing in your options to the littleBIGtable component:

let opts = {
  icons: "https://unpkg.com/littlebigtable@0.1.1/dist/icons.svg"
}
<div x-data="littleBIGtable(opts)" x-init="init()">

</div>

Manually

Copy the icons.svg and littelBIGtable.min.js files from the dist folder into your project somewhere and add the following script element.

<script src="/path/to/your/folder/littleBIGtable.min.js"></script>

You will need to change the icons.svg locations as well, see the examples for details.

<svg><use xlink:href="/path/to/your/install/folder/icons.svg#[name-of-icon]"></use></svg>

Using npm

There is an npm package for littleBIGtable available for install, however it is not recommended until the package is updated.

npm install littlebigtable

Documentation

Get started

This is the starting point for all littleBIGtables, you must wrap your table in an AlpineJS component, provide a url to your api endpoint and specify your table columns and rows. The code below is an example of the minium required.

<div x-data="littleBIGtable({url:'/location/of/your/api'})" x-init="init()">
	<table>
		<thead>
			<tr>
				<th>Title</th>
				<th>Year</th>
				<th>Rating</th>
			</tr>	
		</thead>
		<tbody>
			<template x-for="row in rows">
				<tr>
					<td x-text="row.title"></td>
					<td x-text="row.year"></td>
					<td x-text="row.rating"></td>
				</tr>	
			</template>
		</tbody>
	</table>
</div>
<script src="/path/to/alpine.min.js" defer></script>
<script src="/path/to/littleBIGtable.min.js"></script>

Check the source of the Basic example to see this in action.

Settings

The following settings can be overriden by passing in an object in the x-data attribute:

Fetching data

littleBIGtable expects a JSON response from your endpoint, the object must contain two properties, an Integer total and an Array data with total being the total number of rows in the remote dataset and data containing the subset of rows to be displayed.

In PHP you might do something like this:

<?php
// the total number of records in the dataset
$total = 100;
// an array of rows to display
$data = [
	[
		'title' => '...',
		'year' => '...',
		'rating' => '...'
	],
	// etc...
];

echo json_encode([
	'total' => $total,
	'data' => $data
]);

In the examples folder you'll find a simple PHP JSON server, it can be started on your local machine by using the built in PHP server, type the following into your terminal:

php -S localhost:8080

Formatting cell contents

Before the cell data is rendered it can be modified using formatters, they are functions that return a string and can be used to add links, classes, show images or anything you can think of.

NB: If you are returning HTML you must us the x-html directive on the <td> element, if you use x-text the HTML will be escaped.

Creating a formatter

To create a formatter add your function into the formatters setting passed to littleBIGtable. Your function will receive the cell value and the complete row data. Whatever you return will be displayed in the cell.

Assuming you have columns called year and rating you can create formatters as follows:

let settings = {
	url: '/path/to/your/endpoint',
	formatters: {
		year: function(year, row) {
			if (year < 2000) {
				return `<span class="blue">${year}</span>`;
			}
			return year;
		},
		rating: function(rating, row) {
			if (rating > 4) {
				return `<span class="green">${rating}</span>`;
			}
			if (rating < 3) {
				return `<span class="red">${rating}</span>`;
			}
			return rating;
		}
	}
}

That example would add the class 'blue' to any year in the last century and add the classes 'red' or 'green' to the rating depending on its value.

Adding functionality

Displaying the statusbar

Show a statusbar to show handy messages to the user, loading state or errors and provide a handy reference to where they are in the results.

Simply add the following somewhere inside your component <div>.

<p x-html="meta.status"></p>

The statusbar messages can be changed in the settings. There are two types of summary text, one displays where the user is in terms of rows visible and total, the other is more book like and shows the current page and total pages.

Showing rows 1 to 10 of 95 results or Showing page 2 of 4

To choose between the two set the value of messages.summary to either rows or pages when passing your settings.

You can also customise the loading and failed state messages by passing messages.loading and messages.failed in your settings.

Adding a row limiter

Row limiters limit the number of rows displayed at any one time, the default is 25 but any number between 1 and 100 can be chosen. Any value chosen by the user is saved in localStorage and reused.

Simply add a drop down and add the '' function. This is limited to between 1 and 100 rows.

Check the Complete example for more details.

Adding a search box

A search box can be used to filter your remote data.

Add the code for the search box, ensuring it is inside the component div (the one with the x-data attribute) and add the following ''

Check the Complete example for more details.

Making columns sortable

Columns can be sorted by adding a <button> element to toggle the sort direction.

Add the <button> element to your th using the x-html and @click directives (docs).

<th>
	Year
	<button 
		type="button" 
		x-html="getSortIcon('year')"
		@click="doSort('year')">
	</button>
</th>
<!-- The above code assumes the year column name is 'year' -->

The getSortIcon() method will automatically show the correct icon state using an icon from icons.svg.

The doSort() method sets the URL sort parameter and fetches the sorted data. The url parameter appears as &sort=column_name:asc or &sort=column_name:dsc depending on the requested sort direction.

Check the Complete example for more details.

Adding HTTP headers

If you need to add or adjust the default HTTP headers pass the headers key in the options, the default headers are shown below:

<script>
  let options = {
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'littleBIGtable'
  },
}
</script>
<div x-data="littleBIGtable(options)" x-init="init()">
  ...
</div>

Changing the URL query arguments

If you need to change the default query argument names pass the args key in the options

<script>
let options = {
  args: {
    offset: 'page',
    limit: 'show_per_page',
    search: 'query',
    sort: 'order_by'
  },
}
</script>
<div x-data="littleBIGtable(options)" x-init="init()">
  ...
</div>

Custom events

It is possible to create custom event handlers, for example to handle a row 'click' add the @click handler to your table rows and provide the name of your custom function which can be included anywhere on the page or in a separate file.

<tr @click="doSomething($event)" data-id="123">

By passing the $event 'magic property' (docs) you'll be able to see all the event propeties, for example to get the data-id attribute of the above clicked row

function doSomething(event) {
	console.log('The row was clicked, below is the event and the data-id of the row');
	console.log(event);
	console.log(event.target.parentNode.attributes['data-id'].value);
}