Table Column Decorators
Classes like Table
and Card
do not render their cell
contents themselves. Instead they rely on Column Decorator class to position content within the
cell.
This is in contrast to View
and Lister
which do not
use Table/Cell and therefore Column decorator is not required.
All column decorators in Agile UI have a base class Table\Column
. Decorators will often
look at the content of the associated value, for example Money
will add cell class negative
only if monetary value is less than zero. The value is taken from Model’s Field object.
Column decorators can also function without associated value. Template
may have no
fields or perhaps display multiple field values. Action
displays interactive buttons
in the table. CheckBox
makes grid rows selectable. Ordering
displays
a draggable handle for re-ordering rows within the table.
A final mention is about Multiformat
, which is a column decorator that can swap-in
any other decorator based on condition. This allows you to change button [Archive] for active records,
but if record is already archived, use a template “Archived on {$archive_date}”.
Generic Column Decorator
Table object relies on a separate class: \Atk4\Ui\Table\Column
to present most of the values. The goals
of the column object is to format anything around the actual values. The type = ‘atk4_money’ will result in
a custom formatting of the value, but will also require column to be right-aligned. To simplify this,
type = ‘atk4_money’ will use a different column class - Table\Column\Money
. There are several others,
but first we need to look at the generic column and understand it’s base capabilities:
A class resposnible for cell formatting. This class defines 3 main methods that is used by the Table when constructing HTML:
- Atk4\Ui\Table\Column::getHeaderCellHtml(\Atk4\Data\Field $field) string
Must respond with HTML for the header cell (<th>
) and an appropriate caption. If necessary
will include “sorting” icons or any other controls that go in the header of the table.
- Atk4\Ui\Table\Column::getTotalsCellHtml(\Atk4\Data\Field $field, $value) string
Provided with the field and the value, format the cell for the footer “totals” row. Table
can rely on various strategies for calculating totals. See Table::addTotals
.
- Atk4\Ui\Table\Column::getDataCellHtml(\Atk4\Data\Field $field) string
Provided with a field, this method will respond with HTML template. When iterating, a combined template will be used to display the values.
A sample template could be:
<td><b>{$name}</b></td>
Note that the “name” here must correspond with the field name inside the Model. You may use multiple field names to format the column:
<td><b>{$year}-{$month}-{$day}</b></td>
The above 3 methods define first argument as a field, however it’s possible to define column without a physical field. This makes sense for situations when column contains multiple field values or if it doesn’t contain any values at all.
Sometimes you do want to inject HTML instead of using row values:
- Atk4\Ui\Table\Column::getHtmlTags($model, $field = null)
Return array of HTML tags that will be injected into the row template. See Injecting HTML for further example.
Decorators for data types
In addition to Table\Column
, Agile UI includes several column implementations.
Link
- class Atk4\Ui\Table\Column\Link
Put <a href..
link over the value of the cell. The page property can be specified to constructor. There
are two usage patterns. With the first you can specify full URL as a string:
$table->addColumn('name', [\Atk4\Ui\Table\Column\Link::class, 'https://google.com/?q={$name}']);
The URL may also be specified as an array. It will be passed to App::url() which will encode arguments:
$table->addColumn('name', [\Atk4\Ui\Table\Column\Link::class, ['details', 'id' => 123, 'q' => $anything]]);
In this case even if $anything = '{$name}'
the substitution will not take place for safety reasons. To
pass on some values from your model, use second argument to constructor:
$table->addColumn('name', [\Atk4\Ui\Table\Column\Link::class, ['details', 'id' => 123], ['q' => 'name']]);
Money
- class Atk4\Ui\Table\Column\Money
Helps decorating monetary values. Will align value to the right and if value is less than zero will also use red text (td class “negative” for Fomantic-UI). The money cells are not wrapped.
For the actual number formatting, see uiPersistence
Status
- class Atk4\Ui\Table\Column\Status
Allow you to set highlight class and icon based on column value. This is most suitable for columns that contain pre-defined values.
If your column “status” can be one of the following “pending”, “declined”, “archived” and “paid” and you would like to use different icons and colors to emphasise status:
$states = [
'positive' => ['paid', 'archived'],
'negative' => ['declined'],
];
$table->addColumn('status', new \Atk4\Ui\Table\Column\Status($states));
Current list of states supported:
positive (checkmark icon)
negative (close icon)
and the default/unspecified state (icon question)
(list of states may be expanded further)
Template
- class Atk4\Ui\Table\Column\Template
This column is suitable if you wish to have custom cell formatting but do not wish to go through the trouble of setting up your own class.
If you wish to display movie rating “4 out of 10” based around the column “rating”, you can use:
$table->addColumn('rating', new \Atk4\Ui\Table\Column\Template('{$rating} out of 10'));
Template may incorporate values from multiple fields in a data row, but current implementation will only work if you assign it to a primary column (by passing 1st argument to addColumn).
(In the future it may be optional with the ability to specify caption).
Image
- class Atk4\Ui\Table\Column\Image
This column is suitable if you wish to have image in your table cell:
$table->addColumn('image_url', new \Atk4\Ui\Table\Column\Image);
Interactive Decorators
Checkbox
- class Atk4\Ui\Table\Column\Checkbox
- Atk4\Ui\Table\Column\Checkbox::jsChecked()
Adding this column will render checkbox for each row. This column must not be used on a field. CheckBox column provides you with a handy jsChecked() method, which you can use to reference current item selection. The next code will allow you to select the checkboxes, and when you click on the button, it will reload $segment component while passing all the id’s:
$box = $table->addColumn(new \Atk4\Ui\Table\Column\CheckBox());
$button->on('click', new JsReload($segment, ['ids' => $box->jsChecked()]));
jsChecked expression represents a JavaScript string which you can place inside a form control, use as argument etc.
Multiformat
Sometimes your formatting may change depending on value. For example you may want to place link
only on certain rows. For this you can use an \Atk4\Ui\Table\Column\Multiformat
decorator:
$table->addColumn('amount', [\Atk4\Ui\Table\Column\Multiformat::class, function (Model $entity) {
if ($entity->get('is_invoiced') > 0) {
return [\Atk4\Ui\Table\Column\Money::class, [\Atk4\Ui\Table\Column\Link::class, 'invoice', ['invoice_id' => 'id']]];
} elseif (abs($entity->get('is_refunded')) < 50) {
return [[\Atk4\Ui\Table\Column\Template::class, 'Amount was <b>refunded</b>']];
}
return [[\Atk4\Ui\Table\Column\Money::class]];
}]);
You supply a callback to the Multiformat decorator, which will then be used to determine the actual set of decorators to be used on a given row. The example above will look at various fields of your models and will conditionally add Link on top of Money formatting.
The callback must return array of seeds like:
[[\Atk4\Ui\Table\Column\Link::class], [\Atk4\Ui\Table\Column\Money::class]]
Multiple decorators will be created and merged.
Note
If you are operating with large tables, code your own decorator, which would be more CPU-efficient.