MarkupAdminDataTable
Renders HTML <table> elements for the ProcessWire admin — supports header/footer rows, sortable columns, resizable columns, responsive (mobile) layouts, action buttons, and more
Though designed for the admin, it can be used anywhere: the default CSS classes
come from the active admin theme (e.g., uk-table for AdminThemeUikit).
$table = $modules->get('MarkupAdminDataTable');
$table->setSortable(true);
$table->headerRow([ 'First name', 'Last name', 'Email' ]);
$table->row([ 'Ryan', 'Cramer', 'ryan@processwire.com' ]);
$table->row([ 'Pete', 'Karges', 'pete@processwire.com' ]);
echo $table->render(); Extends ModuleJS (which extends WireData), so it inherits the set(), get(),
setArray(), and other WireData methods. The module is not singular and not
autoload — each $modules->get('Markup call returns a fresh instance
with empty rows.
Expand all Collapse all API reference
| Constant | Value | Description |
|---|---|---|
responsiveNo | 0 | Responsive mode off — table keeps its layout on all screen sizes |
responsiveYes | 1 | Default — on mobile each <td> becomes a row with <th> beside it |
responsiveAlt | 2 | On mobile, <th> and <td> stack vertically instead of side-by-side |
Read-only properties (internal state arrays):
| Property | Type | Description |
|---|---|---|
headerRow | array | Header row labels as passed to headerRow() |
footerRow | array | Footer row data as prepared from footerRow() |
rows | array | All body rows added via row() |
rowClasses | array | CSS class strings per row, indexed by row number |
rowAttrs | array | Attribute arrays per row, indexed by row number |
actions | array | Action buttons (label => URL) from action() |
Read/write properties (settable via $table->property = $value or $table->set()):
| Property | Type | Default | Description |
|---|---|---|---|
encodeEntities | bool | true | Entity-encode cell content (set false if pre-encoded or raw HTML) |
sortable | bool | true | Enable client-side column sorting (requires a header row) |
resizable | bool | false | Enable client-side column resizing |
class | string | '' | Additional CSS class(es) for the <table> |
caption | string | '' | Content for the <caption> element |
responsive | int | responsiveYes (1) | Responsive mode — use a class constant |
id | string | auto (AdminDataTableN) | HTML id attribute (auto-generated when empty) |
border | int|string | '' | HTML border attribute (empty = omitted) |
settings | array | (see init) | Internal settings array (class names, load flags, etc.) |
headerRow(array $labels)
Set the table's header row (<thead>). Each element becomes a <th>. An element may
itself be a two-element array where index 0 is the label and index 1 is a CSS class
for that <th>.
// Simple headers
$table->headerRow([ 'First name', 'Last name', 'Email' ]);
// 4th header cell with a custom class (e.g. right-align it)
$table->headerRow([ 'First name', 'Last name', 'Email', ['Status', 'actions'] ]);Returns $this for chaining.
footerRow(array $labels)
Set the table's footer row (<tfoot>). Each element becomes a <td>. Values may be
plain strings.
$table->footerRow([ 'Total', '', '$5,200' ]);Returns $this for chaining.
row(array $cells, array $options = [])
Add one body row. Each element of $cells becomes a <td>. Elements may take several
forms:
| Element form | HTML result |
|---|---|
'string' | <td>string</td> |
['key' => 'value'] | <td><a href='value'>key</a></td> |
['label' => 'url'] (count 1) | <td><a href='url'>label</a></td> |
['label', 'class'] | <td class='class'>label</td> |
true | Skip this column — the preceding column expands (colspan) |
The $options array supports:
| Option | Type | Description |
|---|---|---|
separator | bool | Show a stronger border above this row (adds AdminDataListSeparator) |
class | string | CSS class(es) for the <tr> |
attrs | array | Key/value attributes for the <tr> (e.g. ['data-id' => '42']) |
// Plain row
$table->row(['Ryan', 'Cramer', 'ryan@processwire.com']);
// First column is a link, second has a CSS class, third is plain
$table->row([
['Ryan' => $pages->get(1)->editUrl],
['Active', 'uk-text-success'],
'ryan@processwire.com'
]);
// Separator row with custom class and a data attribute
$table->row(
['Q1', '$1,200', '$1,500'],
['separator' => true, 'class' => 'highlight', 'attrs' => ['data-quarter' => '1']]
);
// Colspan: 'Summary' expands into the next column (via true)
$table->row(['Summary', true, '$3,000']);Returns $this for chaining.
action(array $action)
Add action button(s) beneath the table. The array maps button labels to URLs
(['label' => 'url']). Each button is rendered with InputfieldButton.
$table->action([ 'Continue' => '../next/' ]);
$table->action([ 'Export CSV' => './export/', 'Import' => './import/' ]);Returns $this for chaining.
setSortable(bool $sortable)
Enable or disable client-side column sorting (via jQuery TableSorter). When enabled,
a header row is required. Sorting is toggled by clicking <th> labels.
$table->setSortable(true); // enable (default)
$table->setSortable(false); // disablesetResizable(bool $resizable)
Enable or disable client-side column resizing. When enabled, jQuery TableSorter's "resizable" widget is loaded.
$table->setResizable(true);setResponsive(int|bool $mode)
Set the responsive (mobile) behavior using one of the class constants:
$table->setResponsive(MarkupAdminDataTable::responsiveNo); // off
$table->setResponsive(MarkupAdminDataTable::responsiveYes); // side-by-side (default)
$table->setResponsive(MarkupAdminDataTable::responsiveAlt); // stacked
$table->setResponsive(false); // same as responsiveNo setEncodeEntities(bool $encodeEntities = true)
Enable or disable HTML entity encoding of cell content. Enabled by default — set
false when content is already entity-encoded or contains intentional HTML markup.
$table->setEncodeEntities(false);
$table->row(['<strong>Bold</strong>', 'Plain text']);setCaption(string $caption)
Set the content for the <caption> element.
$table->setCaption('Page list — sorted by created date');setColNotSortable(int $index)
Mark a column (0-indexed) as non-sortable. The <th> for that column gets the
sorter-false class so jQuery TableSorter ignores it.
// Columns 0 and 1 are checkbox and image — don't sort them
$table->setColNotSortable(0);
$table->setColNotSortable(1);setClass(string $class)
Replace the additional CSS class(es) on the <table> element. Default CMS classes
like AdminDataList are always applied; this sets extra classes on top of them.
$table->setClass('my-custom-table');addClass(string $class)
Add a CSS class to the <table> without replacing existing ones.
$table->addClass('highlight-rows');
$table->addClass('no-stripes');removeClass(string $class)
Remove a CSS class from the <table>. Accepts multiple space-separated classes.
Applied at render time.
$table->removeClass('AdminDataTableSortable');setID(string $id)
Set the HTML id attribute for the <table>. If omitted, an auto-generated id
(AdminDataTable1, AdminDataTable2, …) is assigned.
$table->setID('my-page-list');render()
Render the full HTML — <table> with optional <caption>, <thead>, <tfoot>,
<tbody>, optional action buttons, and a <script> tag for responsive initialization
when applicable.
echo $table->render();If no rows were added, render() returns an empty string (or just the action buttons
if any were defined).
The render() method is hookable (___render()), allowing you to alter the output:
$wire->addHookAfter('MarkupAdminDataTable::render', function(HookEvent $event) {
// Add a footnote after every table
$event->return .= "\n<p class='note'>Updated weekly.</p>";
}); Default CSS class names and whether to load CSS/JS can be customised via
$config->Markup (e.g. in site/config.php):
$config->MarkupAdminDataTable = [
'class' => 'AdminDataTable AdminDataList',
'addClass' => '',
'responsiveClass' => 'AdminDataTableResponsive',
'responsiveAltClass'=> 'AdminDataTableResponsiveAlt',
'sortableClass' => 'AdminDataTableSortable',
'resizableClass' => 'AdminDataTableResizable',
'loadStyles' => true,
'loadScripts' => true,
]; - Instantiation:
$modules->get('Markup— the module is not singular, so each call returns a fresh, empty instance.Admin Data Table') - CSS & JS files are registered automatically via ModuleJS on
init()and appear in$config->stylesand$config->scripts. - Client-side sorting, resizing, and responsive behaviour require jQuery and
jQuery TableSorter, both bundled with the admin theme. The bundled
Markupalso adds shift-click range selection for checkbox columns.Admin Data Table.js - Entity encoding is on by default. Set
encodeEntities = falseif you need raw HTML in cells. - Source file:
wire/modules/Markup/MarkupAdmin Data Table/Markup Admin Data Table.module
API reference: methods, properties, hooks
This module provides a consistent way for rendering <table> elements in the ProcessWire admin. It can certainly be used outside of the admin as well, but it gets its default classes from those
defined by the admin theme. For example, if your system uses AdminThemeUikit then this module
will use uk-table classes.
$table = $modules->get('MarkupAdminDataTable');
$table->setSortable(true);
$table->headerRow([ 'First name', 'Last name', 'Email' ]);
foreach($people as $person) {
$table->row([ $person->first_name, $person->last_name, $person->email ]);
}
echo $table->render(); This module populates Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the Add action button(s) underneath the table Set the footer row for the table Set the header row for the table Render the table Add a row to the table (see arguments for details) Set table caption Set a column as not sortable (first column is 0) Set whether or not entity encoding is enabled Set whether or not table is resizable Set the responsive mode of this table Set whether or not table is sortable Add a class to the <table> without replacing existing ones Remove a class from the <table> Set class(es) to add to <table> Set table id attribute In addition to the methods and properties above, Markup$config->styles and $config->scripts with its MarkupAdminDatable.css and MarkupMarkup class also inherits all the methods and properties of: ModuleJS, WireData and Wire.Common
Name Return Summary $this Content
Name Return Summary self
Can also be used as property: $table->footerRow self
Can also be used as property: $table->headerRow stringself None Settings
Name Return Summary None None None None None Attributes
Name Return Summary None None None None Properties
Name Return Summary $table->actions array Action buttons for under the table $table->border int Table border attribute $table->caption string Content for table <caption> tag. $table->class string Class attribute for <table> element $table->encodeEntities bool Should table content be entity encoded? Set to false if already encoded. $table->id string HTML id attribute for table $table->resizable bool Should table be resizable? $table->responsive bool Use responsive mode? 0=off, 1=responsive, 2=responsive stack $table->rowAttrs array Attributes for table rows indexed by row number (0 is first) $table->rowClasses array Classes for table rows indexed by row number (0 is first) $table->rows array Table rows $table->settings array Array of table settings $table->sortable bool Should table be sortable? Additional methods and properties
API reference based on ProcessWire core version 3.0.269