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\Column
Generic description of a column for
Atk4\Ui\Table
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:
-
getHeaderCellHtml(Atk4DataField $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.
-
getTotalsCellHtml(Atk4DataField $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
.
-
getDataCellHtml(Atk4DataField $field): string
Provided with a field, this method will respond with HTML template. In order to keep performance of Web Application at the maximum, Table will execute getDataCellHtml for all the fields once. When iterating, a combined template will be used to display the values.
The template must not incorporate field values (simply because related model will not be
loaded just yet), but instead should resort to tags and syntax compatible with Template
.
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\
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¶
-
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¶
-
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¶
-
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¶
-
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 asign 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¶
-
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¶
ActionButtons¶
-
Table\Column\ActionButtons
Can be used to add “action buttons” column to your table:
$action = $table->addColumn(null, [Table\Column\ActionButtons::class]);
If you want to have label above the action column, then:
$action = $table->addColumn(null, [Table\Column\ActionButtons::class, 'caption' => 'User Actions']);
-
Atk4\Ui\
addButton
($button, $action, $confirm = false)¶
Adds another button into “Actions” column which will perform a certain JavaScript action when clicked.
See also Atk4\Ui\Grid::addActionButton()
:
$button = $action->addButton('Reload Table', $table->jsReload());
Normally you would also want to pass the ID of the row which was clicked. You can use Atk4\Ui\Table:jsRow()
and jQuery’s data() method to reference it:
$button = $action->addButton('Reload Table', $table->jsReload(['clicked' => $table->jsRow()->data('id')]));
Moreover you may pass $action argument as a PHP callback.
-
Atk4\Ui\
addModal
($button, $title, $callback)¶
Triggers a modal dialog when you click on the button. See description on Atk4\Ui\Grid::addModalAction()
:
$action->addButton(['Say HI'], function (Jquery $j, $id) use ($g) {
return 'Loaded "' . $g->model->load($id)->get('name') . '" from ID=' . $id;
});
Note that in this case ID is automatically passed to your call-back.
Checkbox¶
-
Table\Column\Checkbox
-
Atk4\Ui\
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 \Atk4Ui\Table\Column\Multiformat decorator:
$table->addColumn('amount', [\Atk4\Ui\Table\Column\Multiformat::class, function (Model $model) {
if ($model->get('is_invoiced') > 0) {
return [\Atk4\Ui\Table\Column\Money::class, [\Atk4\Ui\Table\Column\Link::class, 'invoice', ['invoice_id' => 'id']]];
} elseif (abs($model->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:
[[Atk4UiTableColumnLink::class], Atk4UiTableColumnMoney::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.