Documentation
Kitchen Sink documentation of style: 'Delos' of skin: 'ILIAS'
Expandable
Description
- Purpose
- An Expandable Tree focusses on the exploration of hierarchically structured data. Its nodes can be expanded to reveal the underlying nodes; nodes in the Expandable Tree can also be closed to hide all underlying nodes. This lets the user decide on the simultaneously shown levels of the data's hierarchy.
- Composition
- A Tree is composed of Nodes. Further levels (sub-Nodes) are indicated by an Expand Glyph for the closed state of the Node and respectively by a Collapse Glyph for the expanded state. If there are no sub-Nodes, no Glyph will be shown at all. It is possible to only render a part of a tree and load further parts on demand.
- Effect
- When clicking a Node, it will expand or collapse, thus showing or hiding its sub-Nodes.
Rules
- Usage
- Expandable Trees SHOULD only be used when there is a reasonably (large) amount of entries.
- Expandable Trees SHOULD NOT be used to display several aspects of one topic/item, like it would be the case when e.g. listing a repository object and its properties as individual nodes.
- Accessibility
- Expandable Trees MUST bear the ARIA role "tree".
- The "aria-label" attribute MUST be set for Expandable Trees.
- The "aria-label" attribute MUST be language-dependant.
- The "aria-label" attribute MUST describe the content of the Tree as precisely as possible. "Tree" MUST NOT be set as label, labels like "Forum Posts" or "Mail Folders" are much more helpful. (Note that "Tree" is already set by the ARIA role attribute.)
- Every Node in der Tree MUST be accessible by keyboard. Note they this does not imply, that all Nodes are tabbable.
- At least Node in the tree MUST be tabbable.
Example 1: Expandable2
declare(strict_types=1); class DataNode { /** * @var string */ protected $label = ""; /** * @var array */ protected $children = []; public function __construct(string $label, array $children = []) { $this->label = $label; $this->children = $children; } public function getLabel() { return $this->label; } public function getChildren() { return $this->children; } } function expandable2() { global $DIC; $f = $DIC->ui()->factory(); $renderer = $DIC->ui()->renderer(); $n11 = new DataNode('1.1'); $n12 = new DataNode('1.2', array(new DataNode('1.2.1'))); $n1 = new DataNode('1', [$n11, $n12]); $data = [$n1]; $recursion = new class implements \ILIAS\UI\Component\Tree\TreeRecursion { public function getChildren($record, $environment = null) : array { return $record->getChildren(); } public function build( \ILIAS\UI\Component\Tree\Node\Factory $factory, $record, $environment = null ) : \ILIAS\UI\Component\Tree\Node\Node { return $factory->simple($record->getLabel()); } }; $tree = $f->tree()->expandable("Label", $recursion) ->withData($data); return $renderer->render($tree); }
Example 2: Expandable async repo
if ($_GET['async_ref']) { $ref = (int) $_GET['async_ref']; expandable_async_repo($ref); exit(); } function expandable_async_repo($ref = null) { global $DIC; $ilTree = $DIC['tree']; if (is_null($ref)) { $do_async = false; $ref = 1; $data = array( $ilTree->getNodeData(1) ); } else { $do_async = true; $data = $ilTree->getChilds($ref); if (count($data) === 0) { return; } } $recursion = new class implements \ILIAS\UI\Component\Tree\TreeRecursion { public function getChildren($record, $environment = null) : array { return []; } public function build( \ILIAS\UI\Component\Tree\Node\Factory $factory, $record, $environment = null ) : \ILIAS\UI\Component\Tree\Node\Node { $ref_id = $record['ref_id']; $label = $record['title'] . ' (' . $record['type'] . ', ' . $ref_id . ')'; $icon = $environment['icon_factory']->standard($record["type"], ''); $url = $this->getAsyncURL($environment, $ref_id); $node = $factory->simple($label, $icon) ->withAsyncURL($url); //find these under ILIAS->Administration in the example tree if ((int) $ref_id > 9 && (int) $ref_id < 20) { $label = $environment['modal']->getShowSignal()->getId(); $node = $factory->simple($label) ->withAsyncURL($url) ->withOnClick($environment['modal']->getShowSignal()); } return $node; } protected function getAsyncURL($environment, string $ref_id) : string { $url = $environment['url']; $base = substr($url, 0, strpos($url, '?') + 1); $query = parse_url($url, PHP_URL_QUERY); parse_str($query, $params); $params['async_ref'] = $ref_id; $url = $base . http_build_query($params); return $url; } }; $f = $DIC->ui()->factory(); $renderer = $DIC->ui()->renderer(); $image = $f->image()->responsive("src/UI/examples/Image/mountains.jpg", "Image source: https://stocksnap.io, Creative Commons CC0 license"); $page = $f->modal()->lightboxImagePage($image, 'Mountains'); $modal = $f->modal()->lightbox($page); $environment = [ 'url' => $DIC->http()->request()->getRequestTarget(), 'modal' => $modal, 'icon_factory' => $f->symbol()->icon() ]; $tree = $f->tree()->expandable("Label", $recursion) ->withEnvironment($environment) ->withData($data); if (!$do_async) { return $renderer->render([$modal, $tree]); } else { echo $renderer->renderAsync([$modal, $tree->withIsSubTree(true)]); } }
Example 3: Expandable
function expandable() { global $DIC; $f = $DIC->ui()->factory(); $renderer = $DIC->ui()->renderer(); $data = [ ['label' => 'root', 'children' => [ ['label' => '1', 'children' => [ ['label' => '1.1', 'children' => [ ['label' => '1.1.1', 'children' => []], ['label' => '1.1.2', 'children' => []] ]], ['label' => '1.2', 'children' => []], ['label' => '1.3', 'children' => []] ]], ['label' => '2', 'children' => [ ['label' => '2.1', 'children' => []], ]], ['label' => '3', 'children' => [ ['label' => '3.1', 'children' => [ ['label' => '3.1.1', 'children' => [ ['label' => '3.1.1.1', 'children' => []], ]], ]], ]], ]] ]; $recursion = new class implements \ILIAS\UI\Component\Tree\TreeRecursion { public function getChildren($record, $environment = null) : array { return $record['children']; } public function build( \ILIAS\UI\Component\Tree\Node\Factory $factory, $record, $environment = null ) : \ILIAS\UI\Component\Tree\Node\Node { $label = $record['label']; $node = $factory->simple($label); if (count($record['children']) === 0) { $node = $node->withOnClick($environment['modal']->getShowSignal()); } if ($label === "root" || $label === "2") { $node = $node->withExpanded(true); } if ($label === "2") { $node = $node->withHighlighted(true); } return $node; } }; $image = $f->image()->responsive("src/UI/examples/Image/mountains.jpg", "Image source: https://stocksnap.io, Creative Commons CC0 license"); $page = $f->modal()->lightboxImagePage($image, 'Mountains'); $modal = $f->modal()->lightbox($page); $environment = [ 'modal' => $modal ]; $tree = $f->tree()->expandable("Label", $recursion) ->withEnvironment($environment) ->withData($data) ->withHighlightOnNodeClick(true); return $renderer->render([ $modal, $tree ]); }
Relations
- Parents
- UIComponent
- Tree