ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
ILIAS\UI\examples\Table\Data Namespace Reference

Data Structures

class  DataTableDemoRepo
 

Functions

 base ()
 
 repo_implementation ()
 
 with_additional_viewcontrols ()
 
 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 mixed $additional_viewcontrol_data,
167 mixed $filter_data,
168 mixed $additional_parameters
169 ): \Generator {
170 $records = $this->getRecords($range, $order);
171 foreach ($records as $idx => $record) {
172 $row_id = (string) $record['usr_id'];
173 $record['achieve_txt'] = $record['achieve'] > 80 ? 'passed' : 'failed';
174 $record['failure_txt'] = "not " . $record["achieve_txt"];
175 $record['repeat'] = $record['achieve'] < 80;
176
177 $icons = [
178 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_checked.svg', '', 'small'),
179 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_unchecked.svg', '', 'small'),
180 $this->ui_factory->symbol()->icon()->custom('assets/images/standard/icon_x.svg', '', 'small'),
181 ];
182 $icon = $icons[2];
183 if ($record['achieve'] > 80) {
184 $icon = $icons[0];
185 }
186 if ($record['achieve'] < 30) {
187 $icon = $icons[1];
188 }
189 $record['achieve'] = $icon;
190
191 yield $row_builder->buildDataRow($row_id, $record)
193 ->withDisabledAction('delete', ($record['login'] === 'superuser'));
194 }
195 }
196
197 public function getTotalRowCount(
198 mixed $additional_viewcontrol_data,
199 mixed $filter_data,
200 mixed $additional_parameters
201 ): ?int {
202 return count($this->getRecords());
203 }
204
205 protected function getRecords(?Range $range = null, ?Order $order = null): array
206 {
207 $records = [
208 ['usr_id' => 123,'login' => 'superuser','email' => 'user@example.com',
209 'last' => (new \DateTimeImmutable())->modify('-1 day') ,'achieve' => 20,'fee' => 0
210 ],
211 ['usr_id' => 867,'login' => 'student1','email' => 'student1@example.com',
212 'last' => (new \DateTimeImmutable())->modify('-10 day'),'achieve' => 90,'fee' => 40
213 ],
214 ['usr_id' => 8923,'login' => 'student2','email' => 'student2@example.com',
215 'last' => (new \DateTimeImmutable())->modify('-8 day'),'achieve' => 66,'fee' => 36.789
216 ],
217 ['usr_id' => 8748,'login' => 'student3_longname','email' => 'student3_long_email@example.com',
218 'last' => (new \DateTimeImmutable())->modify('-300 day'),'achieve' => 8,'fee' => 36.789
219 ],
220 ['usr_id' => 8749,'login' => 'studentAB','email' => 'studentAB@example.com',
221 'last' => (new \DateTimeImmutable())->modify('-7 day'),'achieve' => 100,'fee' => 114
222 ],
223 ['usr_id' => 8750,'login' => 'student5','email' => 'student5@example.com',
224 'last' => new \DateTimeImmutable(),'achieve' => 76,'fee' => 3.789
225 ],
226 ['usr_id' => 8751,'login' => 'student6','email' => 'student6@example.com',
227 'last' => (new \DateTimeImmutable())->modify('-2 day'),'achieve' => 66,'fee' => 67
228 ]
229 ];
230 if ($order) {
231 list($order_field, $order_direction) = $order->join([], fn($ret, $key, $value) => [$key, $value]);
232 usort($records, fn($a, $b) => $a[$order_field] <=> $b[$order_field]);
233 if ($order_direction === 'DESC') {
234 $records = array_reverse($records);
235 }
236 }
237 if ($range) {
238 $records = array_slice($records, $range->getStart(), $range->getLength());
239 }
240
241 return $records;
242 }
243 };
244
245
250 $table = $f->table()
251 ->data($data_retrieval, 'a data table', $columns)
252 ->withId('example_base')
253 ->withActions($actions)
254
255 //these are initial settings that apply if the according view control
256 //has not been operated, yet
257 ->withRange(new Range(0, 2))
258 ->withOrder(new Order('achieve', Order::DESC))
259 ->withRequest($request);
260
264 $out = [$table];
265
270 $query = $DIC->http()->wrapper()->query();
271 if ($query->has($action_parameter_token->getName())) {
272 $action = $query->retrieve($action_parameter_token->getName(), $refinery->to()->string());
274 $ids = $query->retrieve($row_id_token->getName(), $refinery->custom()->transformation(fn($v) => $v));
275 $listing = $f->listing()->characteristicValue()->text([
276 'table_action' => $action,
277 'id' => print_r($ids, true),
278 ]);
279
281 if ($action === 'delete') {
282 $items = [];
283 foreach ($ids as $id) {
284 $items[] = $f->modal()->interruptiveItem()->keyValue($id, $row_id_token->getName(), $id);
285 }
286 echo($r->renderAsync([
287 $f->modal()->interruptive(
288 'Deletion',
289 'You are about to delete items!',
290 '#'
291 )->withAffectedItems($items)
292 ->withAdditionalOnLoadCode(static fn($id): string => "console.log('ASYNC JS');")
293 ]));
294 exit();
295 }
296 if ($action === 'info') {
297 echo(
298 $r->render($f->messageBox()->info('an info message: <br><li>' . implode('<li>', $ids)))
299 . '<script data-replace-marker="script">console.log("ASYNC JS, too");</script>'
300 );
301 exit();
302 }
303
305 $out[] = $f->divider()->horizontal();
306 $out[] = $listing;
307 }
308
309 return $r->render($out);
310}
$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

References Vendor\Package\$a, Vendor\Package\$b, ILIAS\UI\examples\Layout\Page\Mail\$DIC, Vendor\Package\$f, $id, $out, ILIAS\UI\Implementation\Component\Table\$range, ILIAS\UI\examples\Layout\Page\Mail\$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}
global $DIC
Definition: shib_login.php:26

References $DIC.

◆ with_additional_viewcontrols()

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

description: > Example showing an Data Table with additional view controls.

expected output: > ILIAS shows the rendered Table Component with

  • two additional Mode View Controls,
  • two additional Field Selection Controls,
  • two additional Sortation Controls.

The first Field Selection Control is from the optional columns.

All Viewcontrols may be operated independently and reflect the chosen value(s).

They do not necessarily influence the table itself.

Please note the parameter $additional_viewcontrol_data

add view controls to the table

Definition at line 31 of file with_additional_viewcontrols.php.

32{
33 global $DIC;
34 $f = $DIC['ui.factory'];
35 $r = $DIC['ui.renderer'];
36 $df = new \ILIAS\Data\Factory();
37 $refinery = $DIC['refinery'];
38 $request = $DIC->http()->request();
39
40 $columns = [
41 'usr_id' => $f->table()->column()->number("User ID")
42 ->withIsSortable(false),
43 'login' => $f->table()->column()->text("Login")
44 ->withIsOptional(true)
45 ->withIsSortable(false),
46 'email' => $f->table()->column()->eMail("eMail")
47 ->withIsOptional(true)
48 ->withIsSortable(false),
49 ];
50
51
55 $data_retrieval = new class ($f, $r) implements I\DataRetrieval {
56 public function __construct(
57 protected \ILIAS\UI\Factory $ui_factory,
58 protected \ILIAS\UI\Renderer $ui_renderer
59 ) {
60 }
61
62 public function getRows(
63 I\DataRowBuilder $row_builder,
64 array $visible_column_ids,
66 Order $order,
67 mixed $additional_viewcontrol_data,
68 mixed $filter_data,
69 mixed $additional_parameters
70 ): \Generator {
71 $records = $this->getRecords($range, $order);
72 foreach ($records as $idx => $record) {
73 $row_id = (string) $record['usr_id'];
74
75 if (in_array('hide_login', $additional_viewcontrol_data[0])) {
76 $record['login'] = '-';
77 }
78 if (in_array('hide_mail', $additional_viewcontrol_data[0])) {
79 $record['email'] = '-';
80 }
81 yield $row_builder->buildDataRow($row_id, $record);
82 }
83 }
84
85 public function getTotalRowCount(
86 mixed $additional_viewcontrol_data,
87 mixed $filter_data,
88 mixed $additional_parameters
89 ): ?int {
90 return count($this->getRecords());
91 }
92
93 protected function getRecords(?Range $range = null, ?Order $order = null): array
94 {
95 return [
96 ['usr_id' => 123,'login' => 'superuser','email' => 'user@example.com',
97 'last' => (new \DateTimeImmutable())->modify('-1 day') ,'achieve' => 20,'fee' => 0
98 ],
99 ['usr_id' => 867,'login' => 'student1','email' => 'student1@example.com',
100 'last' => (new \DateTimeImmutable())->modify('-10 day'),'achieve' => 90,'fee' => 40
101 ],
102 ['usr_id' => 8923,'login' => 'student2','email' => 'student2@example.com',
103 'last' => (new \DateTimeImmutable())->modify('-8 day'),'achieve' => 66,'fee' => 36.789
104 ]
105 ];
106 }
107 };
108
109 $table = $f->table()
110 ->data(
111 $data_retrieval,
112 'a data table with additional view controls',
113 $columns
114 )
118 ->withAdditionalViewControl(
119 $f->input()->viewControl()->group(
120 [
121 $f->input()->viewControl()->mode([
122 'show_login' => 'show login',
123 'hide_login' => 'anon login'
124 ])
125 ->withValue('show_login'),
126
127 $f->input()->viewControl()->mode([
128 'show_mail' => 'show mails',
129 'hide_mail' => 'anon mails'
130 ])
131 ->withValue('show_mail'),
132
133 $f->input()->viewControl()->fieldSelection([
134 'opt1' => 'option 1',
135 'opt2' => 'option 2',
136 'opt3' => 'option 3',
137 ]),
138 $f->input()->viewControl()->fieldSelection([
139 'opt1' => 'option 1',
140 'opt2' => 'option 2',
141 'opt3' => 'option 3',
142 ]),
143
144 $f->input()->viewControl()->sortation([
145 'Field 1, ascending' => new Order('field1', 'ASC'),
146 'Field 1, descending' => new Order('field1', 'DESC'),
147 ]),
148 $f->input()->viewControl()->sortation([
149 'Field 1, ascending' => new Order('field1', 'ASC'),
150 'Field 1, descending' => new Order('field1', 'DESC'),
151 ]),
152
153 ]
154 )
155 )
156 ->withRequest($request);
157
158 return $r->render($table->withId('_addvc_example'));
159
160}

References $DIC, Vendor\Package\$f, ILIAS\UI\Implementation\Component\Table\$range, ILIAS\UI\examples\Layout\Page\Mail\$refinery, and ILIAS\__construct().

+ Here is the call graph for this function:

◆ 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 mixed $additional_viewcontrol_data,
54 mixed $filter_data,
55 mixed $additional_parameters
56 ): Generator {
57 yield from [];
58 }
59
60 public function getTotalRowCount(
61 mixed $additional_viewcontrol_data,
62 mixed $filter_data,
63 mixed $additional_parameters
64 ): ?int {
65 return 0;
66 }
67 };
68
69 $table = $factory->table()->data(
70 $empty_retrieval,
71 'Empty Data Table',
72 [
73 'col1' => $factory->table()->column()->text('Column 1')
74 ->withIsSortable(false),
75 'col2' => $factory->table()->column()->number('Column 2')
76 ->withIsSortable(false),
77 ],
78 );
79
80 return $renderer->render($table->withRequest($request));
81}
$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: