UPDATE-RATE

Die Test-Installation wird aktuell zwischen 8:00 und 18:00 Uhr stündlich zur vollen Stunde aktualisiert.

Alles neu macht der Mai

ILIAS 9 ist da! Alle Infos zu den Highlights der neuen Version gibt es hier!

Documentation

Kitchen Sink documentation of style: 'Delos' of skin: 'ILIAS'

Expandable

Description

Purpose
An Expandable Tree focuses 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
  1. Expandable Trees SHOULD only be used when there is a reasonably (large) amount of entries.
  2. 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
  1. Expandable Trees MUST bear the ARIA role "tree".
  2. The "aria-label" attribute MUST be set for Expandable Trees.
  3. The "aria-label" attribute MUST be language-dependant.
  4. 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.)
  5. Every Node in der Tree MUST be accessible by keyboard. Note they this does not imply, that all Nodes are tabbable.
  6. At least Node in the tree MUST be tabbable.

Example 1: Expandable2

<?php
 
declare(strict_types=1);
 
namespace ILIAS\UI\examples\Tree\Expandable;
 
function expandable2(): string
{
    global $DIC;
    $f = $DIC->ui()->factory();
    $renderer = $DIC->ui()->renderer();
 
    $getDataNode = function (string $label, array $children = []) {
        return new class ($label, $children) {
            protected string $label = '';
            protected array$children = [];
 
            public function __construct(string $label, array $children = [])
            {
                $this->label = $label;
                $this->children = $children;
            }
 
            public function getLabel(): string
            {
                return $this->label;
            }
 
            public function getChildren(): array
            {
                return $this->children;
            }
        };
    };
 
    $n11 = $getDataNode('1.1');
    $n12 = $getDataNode('1.2', [$getDataNode('1.2.1')]);
    $n1 = $getDataNode('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

<?php
 
declare(strict_types=1);
 
namespace ILIAS\UI\examples\Tree\Expandable;
 
global $DIC;
$refinery = $DIC->refinery();
$request_wrapper = $DIC->http()->wrapper()->query();
 
if ($request_wrapper->has('async_ref') && $request_wrapper->retrieve('async_ref', $refinery->kindlyTo()->bool())) {
    $ref = $request_wrapper->retrieve('async_ref', $refinery->kindlyTo()->int());
    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, (string) $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);
            if ($query) {
                parse_str($query, $params);
            } else {
                $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

<?php
 
declare(strict_types=1);
 
namespace ILIAS\UI\examples\Tree\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
  1. UIComponent
  2. Tree