| description | This plugin provides a mechanism for creating tables which can have rows added or removed by the user. Very useful for generating forms which the user can control. |
|---|
Dynamic tables are comprised of four main components:
The container element should be an element with the class js-admin-dynamic-table, typically this will be a <table> element, however this is not a requirement. Feel free to include normal table elements (e.g. <thead>) if it makes sense for your use-case:
<table class="js-admin-dynamic-table">
<!-- other elements excluded for brevity -->
<thead>
<tr>
<th>Label</th>
<th>Description</th>
</tr>
</thead>
</table>
The template is the markup which is repeated for each row, it should be a non-rendering child element of the container, e.g. a <script> element. It should be given the class js-admin-dynamic-table__template.
<table class="js-admin-dynamic-table">
<!-- other elements excluded for brevity -->
<script type="text/x-template" class="js-admin-dynamic-table__template">
<tr>
<td>
<input name="foo[{{index}}][label]" value="{{label}}"/>
</td>
<td>
<input name="foo[{{index}}][description]" value="{{description}}"/>
</td>
</tr>
</script>
</table>
{% hint style="info" %}
Each time the template is rendered it will be parsed using Mustache syntax; an {{index}} property will always be made available, along with any custom data you provide.
{% endhint %}
The body is the target element where rows will be rendered, this should be given the class js-admin-dynamic-table__body.
<table class="js-admin-dynamic-table">
<!-- other elements excluded for brevity -->
<tbody class="js-admin-dynamic-table__body"></tbody>
</table>
Any element with the class js-admin-dynamic-table__add will, when clicked, add a new row to the body. Typically this will be in the <tfoot>:
<table class="js-admin-dynamic-table">
<!-- other elements excluded for brevity -->
<tfoot>
<tr>
<td colspan="2">
<button class="js-admin-dynamic-table__add">
Add Row
</button>
</td>
</tr>
</tfoot>
</table>
Any element contained within a row with the class js-admin-dynamic-table__remove will remove the closes <tr> element when clicked. A template with a remove button might look like this:
<table class="js-admin-dynamic-table">
<!-- other elements excluded for brevity -->
<script type="text/x-template">
<tr>
<td>
<input type="text" name="foo[{{index}}][label]" value="{{label}}" />
</td>
<td>
<input type="text" name="foo[{{index}}][description]" value="{{description}}" />
</td>
<td>
<button class="js-admin-dynamic-table__remove">
×
</button>
</td>
</tr>
</script>
</table>
To populate the table with data you can provide a data data attribute on the container. This should be a JSON array of objects, each will represent a row and be avaialble to the rendering of the template:
<?php
$aData = [
['foo' => 'bar', 'fizz' => 'buzz'],
['foo' => 'bar', 'fizz' => 'buzz'],
];
$sData = json_encode($aData);
// Important to escape quotes
$sData = htmlspecialchars($aData);
?>
<table class="js-admin-dynamic-table" data-data="<?=$sData?>">
<!-- other elements excluded for brevity -->
</table>This plugin plays well with the Sortable plugin. Add the class js-admin-sortable to the root element to allow the user to sort the records.
This is a complete working example of a Dynamic Table, which also uses the Sortable plugin:
<?php
$aData = [
['id' => 1, 'order' => 0, 'label' => 'foo', 'description' => 'bar'],
['id' => 2, 'order' => 1, 'label' => 'foo', 'description' => 'bar'],
];
$sData = json_encode($aData);
$sData = htmlspecialchars($aData);
?>
<table class="js-admin-dynamic-table" data-data="<?=$sData?>">
<thead>
<tr>
<th colspan="2">Label</th>
<th colspan="2">Description</th>
</tr>
</thead>
<!-- the body tag plus sortable plugin, configured to use .handle for dragging -->
<tbody class="js-admin-dynamic-table__body js-admin-sortable" data-handle=".handle"></tbody>
<!-- tfoot element for adding new rows -->
<tfoot>
<tr>
<td colspan="4">
<button class="btn btn-sm btn-success js-admin-dynamic-table__add">
+ Add Item
</button>
</td>
</tr>
</tfoot>
<!-- the row template -->
<script type="text-template" class="js-admin-dynamic-table__template">
<tr>
<!-- sorting handle and hidden fields for item ID and sort order -->
<td class="handle" style="width: 15px;">
<b class="fa fa-bars"></b>
<input type="hidden" name="foo[{{index}}][id]" value="{{id}}" />
<input type="hidden" name="foo[{{index}}][order]" value="{{order}}" />
</td>
<!-- label and description cells -->
<td>
<input type="text" name="foo[{{index}}][label]" value="{{label}}" />
</td>
<td>
<input type="text" name="foo[{{index}}][label]" value="{{label}}" />
</td>
<!-- remove row -->
<td style="width: 15px;">
<button class="btn btn-sm btn-danger js-admin-dynamic-table__remove">
×
</button>
</td>
</tr>
</script>
</table>