ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ILIAS\UI\examples\Table\Data Namespace Reference

Data Structures

class  DataTableDemoRepo
 

Functions

 base ()
 
 repo_implementation ()
 
 without_data ()
 

Function Documentation

◆ base()

ILIAS\UI\examples\Table\Data\base ( )

expected output: >

ILIAS shows the rendered Component.

This is what the table will look like: Columns define the nature (and thus: shape) of one field/aspect of the data record. Also, some functions of the table are set per column, e.g. sortability

Define actions: An Action is an URL carrying a parameter that references the targeted record(s). Standard Actions apply to both a collection of records as well as a single entry, while Single- and Multiactions will only work for one of them. Also see the docu-entries for Actions.

this is the endpoint for actions, in this case the same page.

Actions' commands and the row-ids affected are relayed to the server via GET. The URLBuilder orchestrates query-paramters (a.o. by assigning namespace)

We have to claim those parameters. In return, there is a token to modify the value of the param; the tokens will work only with the given copy of URLBuilder, so acquireParameters will return the builder as first entry, followed by the tokens.

array<string, Action> [action_id => Action]

the label as shown in dropdowns

set the actions-parameter's value; will become '&datatable_example_table_action=edit'

the Table will need to modify the values of this parameter; give the token.

An async Action will trigger an AJAX-call to the action's target and display the results in a modal-layer over the Table. Parameters are passed to the call, but you will have to completely build the contents of the response. DO NOT render an entire page ;)

Configure the Table to retrieve data with an instance of DataRetrieval; the table itself is agnostic of the source or the way of retrieving records. However, it provides View Controls and therefore parameters that will influence the way data is being retrieved. E.g., it is usually a good idea to delegate sorting to the database, or limit records to the amount of actually shown rows. Those parameters are being provided to DataRetrieval::getRows.

Actions may be disabled for specific rows:

setup the Table and hand over the request; with an ID for the table, parameters will be stored throughout url changes

build some output.

get the desired action from query; the parameter is namespaced, but we still have the token and it knows its name:

also get the row-ids and build some listing

take care of the async-call; 'delete'-action asks for it.

otherwise, we want the table and the results below

Definition at line 36 of file base.php.

37{
38 global $DIC;
39 $f = $DIC['ui.factory'];
40 $r = $DIC['ui.renderer'];
41 $df = new \ILIAS\Data\Factory();
42 $refinery = $DIC['refinery'];
43 $request = $DIC->http()->request();
44
50 $columns = [
51 'usr_id' => $f->table()->column()->number("User ID")
52 ->withIsSortable(false),
53 'login' => $f->table()->column()->text("Login")
54 ->withHighlight(true),
55 'email' => $f->table()->column()->eMail("eMail"),
56 'last' => $f->table()->column()->date("last login", $df->dateFormat()->germanLong()),
57 'achieve' => $f->table()->column()->statusIcon("progress")
58 ->withIsOptional(true),
59 'achieve_txt' => $f->table()->column()->status("success")
60 ->withIsSortable(true)
61 ->withIsOptional(true, false),
62 'repeat' => $f->table()->column()->boolean("repeat", 'yes', 'no')
63 ->withIsSortable(false),
64 'fee' => $f->table()->column()->number("Fee")
65 ->withDecimals(2)
66 ->withUnit('£', I\Column\Number::UNIT_POSITION_FORE)
67 ->withOrderingLabels('cheapest first', 'most expensive first'),
68 'failure_txt' => $f->table()->column()->status("failure")
69 ->withIsSortable(false)
70 ->withIsOptional(true, false),
71 ];
72
82 $here_uri = $df->uri($DIC->http()->request()->getUri()->__toString());
83
88 $url_builder = new URLBuilder($here_uri);
89 $query_params_namespace = ['datatable', 'example'];
90
97 list($url_builder, $action_parameter_token, $row_id_token) =
98 $url_builder->acquireParameters(
99 $query_params_namespace,
100 "table_action", //this is the actions's parameter name
101 "student_ids" //this is the parameter name to be used for row-ids
102 );
103
107 $actions = [
108 'edit' => $f->table()->action()->single( //never in multi actions
110 'Properties',
112 $url_builder->withParameter($action_parameter_token, "edit"),
114 $row_id_token
115 ),
116 'compare' => $f->table()->action()->multi( //never in single row
117 'Add to Comparison',
118 $url_builder->withParameter($action_parameter_token, "compare"),
119 $row_id_token
120 ),
121 'delete' =>
122 $f->table()->action()->standard( //in both
123 'Remove Student',
124 $url_builder->withParameter($action_parameter_token, "delete"),
125 $row_id_token
126 )
133 ->withAsync(),
134 'info' =>
135 $f->table()->action()->standard( //in both
136 'Info',
137 $url_builder->withParameter($action_parameter_token, "info"),
138 $row_id_token
139 )
140 ->withAsync()
141 ];
142
143
144
154 $data_retrieval = new class ($f, $r) implements I\DataRetrieval {
155 public function __construct(
156 protected \ILIAS\UI\Factory $ui_factory,
157 protected \ILIAS\UI\Renderer $ui_renderer
158 ) {
159 }
160
161 public function getRows(
162 I\DataRowBuilder $row_builder,
163 array $visible_column_ids,
165 Order $order,
166 ?array $filter_data,
167 ?array $additional_parameters
168 ): \Generator {
169 $records = $this->getRecords($range, $order);
170 foreach ($records as $idx => $record) {
171 $row_id = (string) $record['usr_id'];
172 $record['achieve_txt'] = $record['achieve'] > 80 ? 'passed' : 'failed';
173 $record['failure_txt'] = "not " . $record["achieve_txt"];
174 $record['repeat'] = $record['achieve'] < 80;
175
176 $icons = [
177 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_checked.svg', '', 'small'),
178 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_unchecked.svg', '', 'small'),
179 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_x.svg', '', 'small'),
180 ];
181 $icon = $icons[2];
182 if ($record['achieve'] > 80) {
183 $icon = $icons[0];
184 }
185 if ($record['achieve'] < 30) {
186 $icon = $icons[1];
187 }
188 $record['achieve'] = $icon;
189
190 yield $row_builder->buildDataRow($row_id, $record)
192 ->withDisabledAction('delete', ($record['login'] === 'superuser'));
193 }
194 }
195
196 public function getTotalRowCount(
197 ?array $filter_data,
198 ?array $additional_parameters
199 ): ?int {
200 return count($this->getRecords());
201 }
202
203 protected function getRecords(?Range $range = null, ?Order $order = null): array
204 {
205 $records = [
206 ['usr_id' => 123,'login' => 'superuser','email' => 'user@example.com',
207 'last' => (new \DateTimeImmutable())->modify('-1 day') ,'achieve' => 20,'fee' => 0
208 ],
209 ['usr_id' => 867,'login' => 'student1','email' => 'student1@example.com',
210 'last' => (new \DateTimeImmutable())->modify('-10 day'),'achieve' => 90,'fee' => 40
211 ],
212 ['usr_id' => 8923,'login' => 'student2','email' => 'student2@example.com',
213 'last' => (new \DateTimeImmutable())->modify('-8 day'),'achieve' => 66,'fee' => 36.789
214 ],
215 ['usr_id' => 8748,'login' => 'student3_longname','email' => 'student3_long_email@example.com',
216 'last' => (new \DateTimeImmutable())->modify('-300 day'),'achieve' => 8,'fee' => 36.789
217 ],
218 ['usr_id' => 8749,'login' => 'studentAB','email' => 'studentAB@example.com',
219 'last' => (new \DateTimeImmutable())->modify('-7 day'),'achieve' => 100,'fee' => 114
220 ],
221 ['usr_id' => 8750,'login' => 'student5','email' => 'student5@example.com',
222 'last' => new \DateTimeImmutable(),'achieve' => 76,'fee' => 3.789
223 ],
224 ['usr_id' => 8751,'login' => 'student6','email' => 'student6@example.com',
225 'last' => (new \DateTimeImmutable())->modify('-2 day'),'achieve' => 66,'fee' => 67
226 ]
227 ];
228 if ($order) {
229 list($order_field, $order_direction) = $order->join([], fn($ret, $key, $value) => [$key, $value]);
230 usort($records, fn($a, $b) => $a[$order_field] <=> $b[$order_field]);
231 if ($order_direction === 'DESC') {
232 $records = array_reverse($records);
233 }
234 }
235 if ($range) {
236 $records = array_slice($records, $range->getStart(), $range->getLength());
237 }
238
239 return $records;
240 }
241 };
242
243
248 $table = $f->table()
249 ->data($data_retrieval, 'a data table', $columns)
250 ->withId('example_base')
251 ->withActions($actions)
252
253 //these are initial settings that apply if the according view control
254 //has not been operated, yet
255 ->withRange(new Range(0, 2))
256 ->withOrder(new Order('achieve', Order::DESC))
257
258 ->withRequest($request);
259
263 $out = [$table];
264
269 $query = $DIC->http()->wrapper()->query();
270 if ($query->has($action_parameter_token->getName())) {
271 $action = $query->retrieve($action_parameter_token->getName(), $refinery->to()->string());
273 $ids = $query->retrieve($row_id_token->getName(), $refinery->custom()->transformation(fn($v) => $v));
274 $listing = $f->listing()->characteristicValue()->text([
275 'table_action' => $action,
276 'id' => print_r($ids, true),
277 ]);
278
280 if ($action === 'delete') {
281 $items = [];
282 foreach ($ids as $id) {
283 $items[] = $f->modal()->interruptiveItem()->keyValue($id, $row_id_token->getName(), $id);
284 }
285 echo($r->renderAsync([
286 $f->modal()->interruptive(
287 'Deletion',
288 'You are about to delete items!',
289 '#'
290 )->withAffectedItems($items)
291 ->withAdditionalOnLoadCode(static fn($id): string => "console.log('ASYNC JS');")
292 ]));
293 exit();
294 }
295 if ($action === 'info') {
296 echo(
297 $r->render($f->messageBox()->info('an info message: <br><li>' . implode('<li>', $ids)))
298 . '<script data-replace-marker="script">console.log("ASYNC JS, too");</script>'
299 );
300 exit();
301 }
302
304 $out[] = $f->divider()->horizontal();
305 $out[] = $listing;
306 }
307
308 return $r->render($out);
309}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$out
Definition: buildRTE.php:24
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Both the subject and the direction need to be specified when expressing an order.
Definition: Order.php:29
join($init, callable $fn)
Definition: Order.php:75
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:29
Definition: UI.php:24
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
exit
An entity that renders components to a string output.
Definition: Renderer.php:31
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
global $DIC
Definition: shib_login.php:26

References Vendor\Package\$a, Vendor\Package\$b, $DIC, Vendor\Package\$f, $id, $out, ILIAS\UI\Implementation\Component\Table\$range, ILIAS\UI\examples\Layout\Page\Standard\$refinery, ILIAS\__construct(), ILIAS\Data\Order\DESC, exit, ILIAS\Data\Range\getLength(), ILIAS\Data\Range\getStart(), and ILIAS\Data\Order\join().

+ Here is the call graph for this function:

◆ repo_implementation()

ILIAS\UI\examples\Table\Data\repo_implementation ( )

expected output: >

ILIAS shows the rendered Component.

A Table is prone to reflect database tables, or, better repository entries. Usually, changes in the available data and their representation go along with each other, so it might be a good idea to keep that together.

Here is an example, in which the DataRetrieval extends the repository in which the UI-code becomes very small for the actual representation.

Please note that the pagination is missing due to an amount of records smaller than the lowest option "number of rows".

Definition at line 34 of file repo_implementation.php.

35{
48 global $DIC;
49 $r = $DIC['ui.renderer'];
50
51 $repo = new DataTableDemoRepo();
52 $table = $repo->getTableForRepresentation();
53
54 return $r->render(
55 $table->withRequest($DIC->http()->request())
56 );
57}

References $DIC.

◆ without_data()

ILIAS\UI\examples\Table\Data\without_data ( )

description: > Example showing a data table without any data and hence no entries, which will automatically display an according message.

expected output: >

ILIAS shows the rendered Component.

Definition at line 39 of file without_data.php.

39 : string
40{
41 global $DIC;
42
43 $factory = $DIC->ui()->factory();
44 $renderer = $DIC->ui()->renderer();
45 $request = $DIC->http()->request();
46
47 $empty_retrieval = new class () implements DataRetrieval {
48 public function getRows(
49 DataRowBuilder $row_builder,
50 array $visible_column_ids,
52 Order $order,
53 ?array $filter_data,
54 ?array $additional_parameters
55 ): Generator {
56 yield from [];
57 }
58
59 public function getTotalRowCount(?array $filter_data, ?array $additional_parameters): ?int
60 {
61 return 0;
62 }
63 };
64
65 $table = $factory->table()->data(
66 $empty_retrieval,
67 'Empty Data Table',
68 [
69 'col1' => $factory->table()->column()->text('Column 1')
70 ->withIsSortable(false),
71 'col2' => $factory->table()->column()->number('Column 2')
72 ->withIsSortable(false),
73 ],
74 );
75
76 return $renderer->render($table->withRequest($request));
77}
$renderer

References $DIC, ILIAS\UI\Implementation\Component\Table\$range, $renderer, and ILIAS\ResourceStorage\Flavour\Machine\DefaultMachines\from().

+ Here is the call graph for this function: