ILIAS  trunk Revision v11.0_alpha-1761-g6dbbfa7b760
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
ILIAS\UI\examples\Table\Data Namespace Reference

Data Structures

class  DataTableDemoRepo
 

Functions

 base ()
 

expected output: > ILIAS shows the rendered Component. More...

 
 repo_implementation ()
 

expected output: > ILIAS shows the rendered Component. More...

 
 without_data ()
 

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

 

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.

References Vendor\Package\$a, Vendor\Package\$b, $DIC, Vendor\Package\$f, $id, $out, $r, 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(), ILIAS\Data\Order\join(), and null.

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,
164  Range $range,
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 }
Interface Observer Contains several chained tasks and infos about them.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
$out
Definition: buildRTE.php:24
global $DIC
Definition: shib_login.php:22
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
exit
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$r
+ 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.

References $DIC, and $r.

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:22
$r

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

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

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,
51  Range $range,
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
global $DIC
Definition: shib_login.php:22
+ Here is the call graph for this function: