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('MarkupAdminDataTable') call returns a fresh instance with empty rows.

Expand all      API reference

Constants
ConstantValueDescription
responsiveNo0Responsive mode off — table keeps its layout on all screen sizes
responsiveYes1Default — on mobile each <td> becomes a row with <th> beside it
responsiveAlt2On mobile, <th> and <td> stack vertically instead of side-by-side
Properties

Read-only properties (internal state arrays):

PropertyTypeDescription
headerRowarrayHeader row labels as passed to headerRow()
footerRowarrayFooter row data as prepared from footerRow()
rowsarrayAll body rows added via row()
rowClassesarrayCSS class strings per row, indexed by row number
rowAttrsarrayAttribute arrays per row, indexed by row number
actionsarrayAction buttons (label => URL) from action()

Read/write properties (settable via $table->property = $value or $table->set()):

PropertyTypeDefaultDescription
encodeEntitiesbooltrueEntity-encode cell content (set false if pre-encoded or raw HTML)
sortablebooltrueEnable client-side column sorting (requires a header row)
resizableboolfalseEnable client-side column resizing
classstring''Additional CSS class(es) for the <table>
captionstring''Content for the <caption> element
responsiveintresponsiveYes (1)Responsive mode — use a class constant
idstringauto (AdminDataTableN)HTML id attribute (auto-generated when empty)
borderint|string''HTML border attribute (empty = omitted)
settingsarray(see init)Internal settings array (class names, load flags, etc.)
Adding content

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 formHTML 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>
trueSkip this column — the preceding column expands (colspan)

The $options array supports:

OptionTypeDescription
separatorboolShow a stronger border above this row (adds AdminDataListSeparator)
classstringCSS class(es) for the <tr>
attrsarrayKey/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.

Settings

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);  // disable

setResizable(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');
Column attributes

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);
Table attributes

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');
Rendering

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).

Hooks

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>";
});
Configurable settings

Default CSS class names and whether to load CSS/JS can be customised via $config->MarkupAdminDataTable (e.g. in site/config.php):

$config->MarkupAdminDataTable = [
    'class'             => 'AdminDataTable AdminDataList',
    'addClass'          => '',
    'responsiveClass'   => 'AdminDataTableResponsive',
    'responsiveAltClass'=> 'AdminDataTableResponsiveAlt',
    'sortableClass'     => 'AdminDataTableSortable',
    'resizableClass'    => 'AdminDataTableResizable',
    'loadStyles'        => true,
    'loadScripts'       => true,
];
Notes
  • Instantiation: $modules->get('MarkupAdminDataTable') — the module is not singular, so each call returns a fresh, empty instance.
  • CSS & JS files are registered automatically via ModuleJS on init() and appear in $config->styles and $config->scripts.
  • Client-side sorting, resizing, and responsive behaviour require jQuery and jQuery TableSorter, both bundled with the admin theme. The bundled MarkupAdminDataTable.js also adds shift-click range selection for checkbox columns.
  • Entity encoding is on by default. Set encodeEntities = false if you need raw HTML in cells.
  • Source file: wire/modules/Markup/MarkupAdminDataTable/MarkupAdminDataTable.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 $config->styles and $config->scripts with its MarkupAdminDatable.css and MarkupAdminDataTable.js files.


Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the MarkupAdminDataTable class also inherits all the methods and properties of: ModuleJS, WireData and Wire.

Show $var?     Show args?       Only hookable?    

Common

NameReturnSummary 
$table->action(array $action)
$this

Add action button(s) underneath the table

 

Content

NameReturnSummary 
$table->footerRow(array $a)
self

Set the footer row for the table


Can also be used as property: $table->footerRow
 
$table->headerRow(array $a)
self

Set the header row for the table


Can also be used as property: $table->headerRow
 
$table->render()
string

Render the table

$table->row(array $a)
self

Add a row to the table (see arguments for details)

 
$table->setCaption(string $caption)
None

Set table caption

 

Properties

NameReturnSummary 
$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

In addition to the methods and properties above, MarkupAdminDataTable also inherits the methods and properties of these classes:

API reference based on ProcessWire core version 3.0.269