19 declare(strict_types=1);
59 throw new \LogicException(self::class .
" cannot render component '" . get_class($component) .
"'.");
66 $tpl = $this->
getTemplate(
"tpl.presentationtable.html",
true,
true);
67 $tpl->setVariable(
"TITLE", $component->getTitle());
68 $expcollapsebtns = [];
69 if ($sig_ta = $component->getExpandCollapseAllSignal()) {
70 $sig_ta_expand = clone $sig_ta;
71 $sig_ta_expand->addOption(
'expand',
true);
73 ->standard($this->
txt(
'presentation_table_expand'),
'')
74 ->withOnClick($sig_ta_expand);
75 $sig_ta_collapse = clone $sig_ta;
76 $sig_ta_collapse->addOption(
'expand',
false);
78 ->standard($this->
txt(
'presentation_table_collapse'),
'')
79 ->withOnClick($sig_ta_collapse);
80 $component = $component->withAdditionalOnLoadCode(
82 il.UI.table.presentation.init('{$id}'); 83 $(document).on('$sig_ta', function(event, signal_data) { il.UI.table.presentation.get('$id').expandAll(signal_data); return false; }); 88 $tpl->setVariable(
"EXPANDCOLLAPSEALL", $default_renderer->render($expcollapsebtns));
90 $vcs = $component->getViewControls();
92 $tpl->setVariable(
"VC", $default_renderer->render($vcs));
96 $tpl->setVariable(
"ID",
$id);
98 $row_mapping = $component->getRowMapping();
99 $data = $component->getData();
107 foreach (
$data as $record) {
112 $component->getEnvironment()
115 $tpl->setCurrentBlock(
"row");
116 $tpl->setVariable(
"ROW", $default_renderer->render($row));
117 $tpl->parseCurrentBlock();
128 $tpl = $this->
getTemplate(
"tpl.presentationrow.html",
true,
true);
131 $sig_show = $component->getShowSignal();
132 $sig_hide = $component->getCloseSignal();
133 $sig_toggle = $component->getToggleSignal();
136 $expander =
$f->symbol()->glyph()->expand(
"#")
137 ->withOnClick($sig_show);
138 $collapser =
$f->symbol()->glyph()->collapse(
"#")
139 ->withOnClick($sig_hide);
140 $shy_expander =
$f->button()->shy($this->
txt(
"presentation_table_more"),
"#")
141 ->withOnClick($sig_show);
143 $tpl->setVariable(
"ID",
$id);
144 $tpl->setVariable(
"EXPANDER", $default_renderer->render($expander));
145 $tpl->setVariable(
"COLLAPSER", $default_renderer->render($collapser));
146 $tpl->setVariable(
"SHY_EXPANDER", $default_renderer->render($shy_expander));
148 if ($symbol = $component->getLeadingSymbol()) {
149 $tpl->setVariable(
"SYMBOL", $default_renderer->render($symbol));
151 $tpl->setVariable(
"HEADLINE", $component->getHeadline());
152 $tpl->setVariable(
"TOGGLE_SIGNAL", $sig_toggle);
153 $subheadline = $component->getSubheadline();
155 $tpl->setVariable(
"SUBHEADLINE", $subheadline);
158 foreach ($component->getImportantFields() as $label => $value) {
159 $tpl->setCurrentBlock(
"important_field");
160 if (is_string($label)) {
161 $tpl->setVariable(
"IMPORTANT_FIELD_LABEL", $label);
163 $tpl->setVariable(
"IMPORTANT_FIELD_VALUE", $value);
164 $tpl->parseCurrentBlock();
167 $tpl->setVariable(
"DESCLIST", $default_renderer->render($component->getContent()));
169 $further_fields_headline = $component->getFurtherFieldsHeadline();
170 $further_fields = $component->getFurtherFields();
172 if (count($further_fields) > 0) {
173 $tpl->touchBlock(
"has_further_fields");
175 if ($further_fields_headline) {
176 $tpl->setVariable(
"FURTHER_FIELDS_HEADLINE", $further_fields_headline);
179 foreach ($further_fields as $label => $value) {
180 $tpl->setCurrentBlock(
"further_field");
181 if (is_string($label)) {
182 $tpl->setVariable(
"FIELD_LABEL", $label);
184 $tpl->setVariable(
"FIELD_VALUE", $value);
185 $tpl->parseCurrentBlock();
189 $action = $component->getAction();
190 if (!is_null($action)) {
191 $tpl->setCurrentBlock(
"button");
192 $tpl->setVariable(
"BUTTON", $default_renderer->render($action));
193 $tpl->parseCurrentBlock();
201 $tpl = $this->
getTemplate(
"tpl.datatable.html",
true,
true);
203 $opt_action_id = Action::OPT_ACTIONID;
204 $opt_row_id = Action::OPT_ROWID;
205 $component = $component
206 ->withAdditionalOnLoadCode(
207 static fn(
$id):
string =>
208 "il.UI.table.data.init('{$id}','{$opt_action_id}','{$opt_row_id}');" 215 foreach ($component->getAllActions() as $action_id => $action) {
216 $component = $component->withAdditionalOnLoadCode($this->
getActionRegistration((
string) $action_id, $action));
217 if ($action->isAsync()) {
218 $signal = clone $component->getAsyncActionSignal();
219 $signal->addOption(Action::OPT_ACTIONID, $action_id);
220 $action = $action->withSignalTarget($signal);
222 $actions[$action_id] = $action;
224 $component = $component->withActions($actions);
226 if ($component->hasMultiActions()) {
227 $component = $component->withAdditionalOnLoadCode(
228 static fn(
$id):
string =>
"il.UI.table.data.get('{$id}').selectAll(false);" 232 [$component, $view_controls] = $component->applyViewControls(
233 $component->getFilter() ?? [],
234 $component->getAdditionalParameters()
237 $tpl->setVariable(
'VIEW_CONTROLS', $default_renderer->render($view_controls));
239 $rows = $component->getDataRetrieval()->getRows(
240 $component->getRowBuilder(),
241 array_keys($component->getVisibleColumns()),
242 $component->getRange(),
243 $component->getOrder(),
244 $component->getFilter(),
245 $component->getAdditionalParameters()
249 $tpl->setVariable(
'ID',
$id);
250 $tpl->setVariable(
'TITLE', $component->getTitle());
251 $tpl->setVariable(
'COL_COUNT', (
string) $component->getColumnCount());
253 $sortation_signal = null;
255 if (!$rows->valid()) {
260 if ($component->hasMultiActions()) {
261 $multi_actions = $component->getMultiActions();
265 $component->getMultiActionSignal(),
266 $modal->getShowSignal()
268 $total_number_of_cols = count($component->getVisibleColumns()) + 2;
269 $tpl->setVariable(
'COLUMN_COUNT', (
string) $total_number_of_cols);
270 $tpl->setVariable(
'MULTI_ACTION_TRIGGERER', $default_renderer->render($multi_actions_dropdown));
271 $tpl->setVariable(
'MULTI_ACTION_ALL_MODAL', $default_renderer->render($modal));
274 $sortation_signal = null;
275 $sortation_view_control = array_filter(
276 $view_controls->getInputs(),
279 if ($sortation_view_control) {
280 $sortation_signal = array_shift($sortation_view_control)->getInternalSignal();
281 $sortation_signal->addOption(
'parent_container',
$id);
285 $this->
renderTableHeader($default_renderer, $component, $tpl, $sortation_signal);
295 $order = $component->getOrder();
296 $glyph_factory = $this->
getUIFactory()->symbol()->glyph();
297 $sort_col = key($order->get());
298 $sort_direction = current($order->get());
299 $columns = $component->getVisibleColumns();
301 foreach ($columns as $col_id => $col) {
303 $col_title = $col->getTitle();
304 if ($col_id === $sort_col) {
306 $sortation = $this->
txt(
'order_option_generic_ascending');
307 $sortation_glyph = $glyph_factory->sortAscending(
"#");
311 $sortation = $this->
txt(
'order_option_generic_descending');
312 $sortation_glyph = $glyph_factory->sortDescending(
"#");
317 $tpl->
setVariable(
'COL_INDEX', (
string) $col->getIndex());
319 if ($col->isSortable() && ! is_null($sortation_signal)) {
320 $sort_signal = clone $sortation_signal;
321 $sort_signal->addOption(
'value',
"$col_id:$param_sort_direction");
322 $col_title = $default_renderer->render(
326 if ($col_id === $sort_col) {
327 $sortation_glyph = $default_renderer->render($sortation_glyph->withOnClick($sort_signal));
329 $tpl->
setVariable(
'COL_SORTATION_GLYPH', $sortation_glyph);
334 $tpl->
setVariable(
'COL_TYPE', strtolower($col->getType()));
338 if ($component->hasSingleActions()) {
339 $tpl->
setVariable(
'COL_INDEX_ACTION', (
string) count($columns));
344 if ($component->hasMultiActions()) {
345 $signal = $component->getSelectionSignal();
346 $sig_all = clone $signal;
347 $sig_all->addOption(
'select',
true);
348 $select_all = $glyph_factory->add()->withOnClick($sig_all);
349 $signal->addOption(
'select',
false);
350 $select_none = $glyph_factory->close()->withOnClick($signal);
351 $tpl->
setVariable(
'SELECTION_CONTROL_SELECT', $default_renderer->render($select_all));
352 $tpl->
setVariable(
'SELECTION_CONTROL_DESELECT', $default_renderer->render($select_none));
362 $cell_tpl = $this->
getTemplate(
'tpl.datacell.html',
true,
true);
363 $cell_tpl->setCurrentBlock(
'cell');
364 $cell_tpl->setVariable(
'CELL_CONTENT', $content);
365 $cell_tpl->setVariable(
'COL_SPAN', count($component->getVisibleColumns()));
366 $cell_tpl->setVariable(
'COL_TYPE',
'full-width');
367 $cell_tpl->setVariable(
'COL_INDEX',
'1');
368 $cell_tpl->parseCurrentBlock();
378 $opt_action_id = Action::OPT_ACTIONID;
379 $opt_row_id = Action::OPT_ROWID;
381 $component = $component
382 ->withAdditionalOnLoadCode(
383 static fn(
$id):
string =>
384 "il.UI.table.data.init('{$id}','{$opt_action_id}','{$opt_row_id}');" 391 foreach ($component->getAllActions() as $action_id => $action) {
392 $component = $component->withAdditionalOnLoadCode($this->
getActionRegistration((
string) $action_id, $action));
393 if ($action->isAsync()) {
394 $signal = clone $component->getAsyncActionSignal();
395 $signal->addOption(Action::OPT_ACTIONID, $action_id);
396 $action = $action->withSignalTarget($signal);
398 $actions[$action_id] = $action;
400 $component = $component->withActions($actions);
402 if ($component->hasMultiActions()) {
403 $component = $component->withAdditionalOnLoadCode(
404 static fn(
$id):
string =>
"il.UI.table.data.get('{$id}').selectAll(false);" 416 if ($component->hasSingleActions()) {
417 $tpl->
setVariable(
'COL_INDEX_ACTION', (
string) count($component->getColumns()));
421 if ($component->hasMultiActions()) {
422 $glyph_factory = $this->
getUIFactory()->symbol()->glyph();
423 $signal = $component->getSelectionSignal();
424 $sig_all = clone $signal;
425 $sig_all->addOption(
'select',
true);
426 $select_all = $glyph_factory->add()->withOnClick($sig_all);
427 $signal->addOption(
'select',
false);
428 $select_none = $glyph_factory->close()->withOnClick($signal);
429 $tpl->
setVariable(
'SELECTION_CONTROL_SELECT', $default_renderer->render($select_all));
430 $tpl->
setVariable(
'SELECTION_CONTROL_DESELECT', $default_renderer->render($select_none));
440 foreach ($rows as $row) {
441 $row_contents = $default_renderer->render($row);
442 $alternate = ($alternate ===
'odd') ?
'even' :
'odd';
452 $row_tpl = $this->
getTemplate(
'tpl.presentationrow_empty.html',
true,
true);
453 $row_tpl->setVariable(
'CONTENT', $content);
466 $msg =
$f->messageBox()->confirmation($this->
txt(
'datatable_multiactionmodal_msg'));
468 $select =
$f->input()->field()->select(
469 $this->
txt(
'datatable_multiactionmodal_actionlabel'),
471 static fn($action):
string => $action->getLabel(),
475 )->withRequired(
true);
476 $submit =
$f->button()->primary($this->
txt(
'datatable_multiactionmodal_apply'),
'')
478 static fn(
$id):
string =>
"$('#{$id}').click(function() { il.UI.table.data.get('{$table_id}').doActionForAll(this); return false; });" 481 ->roundtrip($this->
txt(
'datatable_multiactionmodal_title'), [$msg, $select])
482 ->withActionButtons([$submit]);
494 if ($actions === []) {
498 $glyph =
$f->symbol()->glyph()->bulletlist();
500 $all_obj_buttons = [];
501 foreach ($actions as $action_id => $act) {
502 $signal = clone $action_signal;
503 $signal->addOption(Action::OPT_ACTIONID, $action_id);
504 $buttons[] =
$f->button()->shy($act->getLabel(), $signal);
507 $buttons[] =
$f->divider()->horizontal();
508 $buttons[] =
$f->button()->shy($this->
txt(
'datatable_multiactionmodal_listentry'),
'#')->withOnClick($modal_signal);
510 return $f->dropdown()->standard($buttons)->withLabel($this->
txt(
'datatable_multiaction_label'));
515 return static function (
$id) use ($action_signal):
string {
517 $(document).on('{$action_signal}', function(event, signal_data) { 518 il.UI.table.data.get('{$id}').doSingleAction(signal_data); 525 return static function (
$id) use ($action_signal):
string {
527 $(document).on('{$action_signal}', function(event, signal_data) { 528 il.UI.table.data.get('{$id}').doMultiAction(signal_data); 536 return static function (
$id) use ($selection_signal):
string {
538 $(document).on('{$selection_signal}', function(event, signal_data) { 539 il.UI.table.data.get('{$id}').selectAll(signal_data.options.select); 550 $async = $action->isAsync() ?
'true' :
'false';
551 $url_builder_js = $action->getURLBuilderJS();
552 $tokens_js = $action->getURLBuilderTokensJS();
554 return static function (
$id) use ($action_id, $async, $url_builder_js, $tokens_js):
string {
556 il.UI.table.data.get('{$id}').registerAction('{$action_id}', {$async}, {$url_builder_js}, {$tokens_js}); 563 $cell_tpl = $this->
getTemplate(
"tpl.datacell.html",
true,
true);
564 $cols = $component->getColumns();
566 foreach ($cols as $col_id => $column) {
567 if ($column->isHighlighted()) {
568 $cell_tpl->touchBlock(
'highlighted');
570 $cell_tpl->setCurrentBlock(
'cell');
571 $cell_tpl->setVariable(
'COL_TYPE', strtolower($column->getType()));
572 $cell_tpl->setVariable(
'COL_INDEX', $column->getIndex());
573 $cell_content = $component->getCellContent($col_id);
575 $cell_content = $default_renderer->render($cell_content);
577 $cell_tpl->setVariable(
'CELL_CONTENT', $cell_content);
578 $cell_tpl->setVariable(
'CELL_COL_TITLE', $component->getColumns()[$col_id]->getTitle());
579 $cell_tpl->parseCurrentBlock();
582 if ($component->tableHasMultiActions()) {
583 $cell_tpl->setVariable(
'ROW_ID', $component->getId());
585 if ($component->tableHasSingleActions()) {
588 $component->getActions()
590 $cell_tpl->setVariable(
'ACTION_CONTENT', $default_renderer->render($row_actions_dropdown));
593 return $cell_tpl->get();
598 $cell_tpl = $this->
getTemplate(
"tpl.orderingcell.html",
true,
true);
599 $this->
fillCells($component, $cell_tpl, $default_renderer);
601 if ($component->isOrderingDisabled()) {
602 return $cell_tpl->get();
605 $namesource =
new class () implements
NameSource {
606 public function getNewName():
string 610 public function getNewDedicatedName(
string $dedicated_name):
string 612 return $dedicated_name;
616 $input = $this->
getUIFactory()->input()->field()->numeric(
'order')
617 ->withDedicatedName($component->getId())
619 ->withValue($component->getPosition() * 10);
620 $cell_tpl->setVariable(
'ORDER_INPUT', $default_renderer->render($input));
622 return $cell_tpl->get();
630 $cols = $row->getColumns();
631 foreach ($cols as $col_id => $column) {
632 if ($column->isHighlighted()) {
636 $cell_tpl->
setVariable(
'COL_TYPE', strtolower($column->getType()));
637 $cell_tpl->
setVariable(
'COL_INDEX', $column->getIndex());
638 $cell_content = $row->getCellContent($col_id);
640 $cell_content = $default_renderer->render($cell_content);
642 $cell_tpl->
setVariable(
'CELL_CONTENT', $cell_content);
643 $cell_tpl->
setVariable(
'CELL_COL_TITLE', $row->getColumns()[$col_id]->getTitle());
647 if ($row->tableHasMultiActions()) {
650 if ($row->tableHasSingleActions()) {
655 $cell_tpl->
setVariable(
'ACTION_CONTENT', $default_renderer->render($row_actions_dropdown));
666 foreach ($actions as $act) {
667 $act = $act->withRowId($row_id);
668 $target = $act->getTarget();
669 if ($target instanceof
URI) {
670 $target = (string) $target;
672 $buttons[] =
$f->button()->shy($act->getLabel(), $target);
674 return $f->dropdown()->standard($buttons);
679 $tpl = $this->
getTemplate(
"tpl.orderingtable.html",
true,
true);
682 [$component, $view_controls] = $component->applyViewControls();
684 $rows = $component->getDataBinding()->getRows(
685 $component->getRowBuilder(),
686 array_keys($component->getVisibleColumns()),
690 if (!$component->isOrderingDisabled()) {
691 $component = $component->withAdditionalOnLoadCode(
692 static fn(
$id):
string =>
"il.UI.table.ordering.init('{$id}');" 697 $total_number_of_cols = count($component->getVisibleColumns());
699 if (!$component->isOrderingDisabled()) {
700 $total_number_of_cols = $total_number_of_cols + 1;
701 $submit = $this->
getUIFactory()->button()->standard($this->
txt(
'sorting_save'),
"")
702 ->withOnLoadCode(
static fn(
$id) =>
"document.getElementById('$id').addEventListener('click', 703 function() {document.querySelector('#$tableid form.c-table-ordering__form').submit();return false;});");
705 $tpl->setVariable(
'FORM_BUTTONS', $default_renderer->render($submit));
706 $tpl->setVariable(
'POS_INPUT_TITLE', $this->
txt(
'table_posinput_col_title'));
709 $tpl->setVariable(
'ID', $tableid);
710 $tpl->setVariable(
'TARGET_URL', $component->getTargetURL() ? $component->getTargetURL()->__toString() :
'#');
711 $tpl->setVariable(
'TITLE', $component->getTitle());
712 $tpl->setVariable(
'COL_COUNT', (
string) $component->getColumnCount());
713 $tpl->setVariable(
'VIEW_CONTROLS', $default_renderer->render($view_controls));
715 $columns = $component->getVisibleColumns();
716 foreach ($columns as $col_id => $col) {
717 $col_title = $col->getTitle();
718 $tpl->setCurrentBlock(
'header_cell');
719 $tpl->setVariable(
'COL_INDEX', (
string) $col->getIndex());
720 $tpl->setVariable(
'COL_TITLE', $col_title);
721 $tpl->setVariable(
'COL_TYPE', strtolower($col->getType()));
722 $tpl->parseCurrentBlock();
725 $rows = iterator_to_array($rows);
727 foreach ($rows as $idx => $row) {
729 ->withPosition($idx + 1)
730 ->withOrderingDisabled($component->isOrderingDisabled());
736 if ($component->hasMultiActions()) {
737 $total_number_of_cols = $total_number_of_cols + 2;
738 $multi_actions = $component->getMultiActions();
742 $component->getMultiActionSignal(),
743 $modal->getShowSignal()
745 $tpl->setVariable(
'MULTI_ACTION_TRIGGERER', $default_renderer->render($multi_actions_dropdown));
746 $tpl->setVariable(
'MULTI_ACTION_ALL_MODAL', $default_renderer->render($modal));
749 $tpl->setVariable(
'COLUMN_COUNT', (
string) $total_number_of_cols);
759 parent::registerResources($registry);
760 $registry->
register(
'./src/UI/templates/js/Table/dist/table.min.js');
761 $registry->
register(
'./src/UI/templates/js/Modal/modal.js');
766 $show = $component->getShowSignal();
767 $close = $component->getCloseSignal();
768 $toggle = $component->getToggleSignal();
769 $table_id = $component->getTableId();
770 return $component->withAdditionalOnLoadCode(
771 static fn(
$id):
string =>
772 "$(document).on('$show', function() { il.UI.table.presentation.get('$table_id').expandRow('$id'); return false; });" .
773 "$(document).on('$close', function() { il.UI.table.presentation.get('$table_id').collapseRow('$id'); return false; });" .
774 "$(document).on('$toggle', function() { il.UI.table.presentation.get('$table_id').toggleRow('$id'); return false; });" 784 Component\Table\PresentationRow::class,
785 Component\Table\Presentation::class,
786 Component\Table\Data::class,
787 Component\Table\DataRow::class,
788 Component\Table\OrderingRow::class,
789 Component\Table\Ordering::class
Registry for resources required by rendered output like Javascript or CSS.
button(string $caption, string $cmd)
checkComponent(Component $component)
Check if a given component fits this renderer and throw if that is not the case. ...
registerSignals(Component\Table\PresentationRow $component)
renderPresentationTable(Component\Table\Presentation $component, RendererInterface $default_renderer)
Class ChatMainBarProvider .
renderTableHeader(RendererInterface $default_renderer, Component\Table\Data $component, Template $tpl, ?Component\Signal $sortation_signal)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getActionRegistration(string $action_id, Action $action)
txt(string $id)
Get a text from the language file.
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
setCurrentBlock(string $name)
Set the block to work on.
createId()
Get a fresh unique id.
This describes commonalities between all types of Dropdowns.
buildMultiActionsAllObjectsModal(array $actions, string $table_id)
setVariable(string $name, $value)
Set a variable in the current block.
render(Component\Component $component, RendererInterface $default_renderer)
getComponentInterfaceName()
renderPresentationRow(Component\Table\PresentationRow $component, RendererInterface $default_renderer)
getSingleActionsForRow(string $row_id, array $actions)
getAsyncActionHandler(Component\Signal $action_signal)
registerActions(Component\Table\Table $component)
renderDataTable(Component\Table\Data $component, RendererInterface $default_renderer)
renderFullWidthDataCell(Component\Table\Data $component, Template $tpl, string $content)
Renders a full-width cell with a single message within, indication there is no data to display...
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
renderDataRow(Component\Table\DataRow $component, RendererInterface $default_renderer)
The scope of this class is split ilias-conform URI's into components.
fillCells(Component\Table\DataRow $row, Template $cell_tpl, RendererInterface $default_renderer)
register(string $name)
Add a dependency.
getSelectionHandler(Component\Signal $selection_signal)
renderOrderingTable(Component\Table\Ordering $component, RendererInterface $default_renderer)
parseCurrentBlock()
Parse the block that is currently worked on.
appendTableRows(Template $tpl, \Generator|array $rows, RendererInterface $default_renderer)
touchBlock(string $name)
Touch a block without working further on it.
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
getUIFactory()
Get a UI factory.
renderEmptyPresentationRow(Template $tpl, RendererInterface $default_renderer, string $content)
getMultiActionHandler(Component\Signal $action_signal)
renderActionsHeader(RendererInterface $default_renderer, Component\Table\Table $component, Template $tpl)
Base class for all component renderers.
renderOrderingRow(Component\Table\OrderingRow $component, RendererInterface $default_renderer)
buildMultiActionsDropdown(array $actions, Component\Signal $action_signal, Component\Signal $modal_signal,)
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.