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'

Presentation

Description

Purpose
The Presentation Table lists some tabular data in a pleasant way. The user can get a quick overview over the records in the dataset, the Presentation Table only shows the most relevant fields of the records at first glance. The records can be expanded to show more extensive information, i.e. additional fields and further information. The Presentation Table represents the displayed dataset an entirety rather than a list of single rows. The table facilitates exploring the dataset, where the purpose of this exploration is known and supported. Single records may be derived and composed of all kind of sources and do not necessarily reference a persistent entity like an ilObject.
Composition
The Presentation Table consists of a title, a slot for View Controls and Presentation Rows. The rows will be prefixed by an Expand Glyph and consist of a headline, a subheadline and a choice of record-fields. The expanded row will show a lists of further fields and, optionally, a button or dropdown for actions. The table is visually represented as a wholeness and does not decompose into several parts.
Effect
Rows can be expanded and collapsed to show/hide more extensive and detailed information per record. A click on the Expand Glyph will enlarge the row vertically to show the complete record and exchange the Expand Glyph by a Collapse Glyph. Fields that were shown in the collapsed row will be hidden except for headline and subheadline. The ordering among the records in the table, the ordering of the fields in one row or the visible contents of the table itself can be adjusted with View Controls. In contrast to the accordions known from the page editor, it is possible to have multiple expanded rows in the table.

Rivals

Data Table
A data-table shows some dataset and offers tools to explore it in a user defined way. Instead of aiming at simplicity the Presentation Table aims at maximum explorability. Datasets that contain long content fields, e.g. free text or images, are hard to fit into a Data Table but can indeed be displayed in a Presentation Table.
Listing Panel
Listing Panels list items, where an item is a unique entity in the system, i.e. an identifiable, persistently stored object. This is not necessarily the case for Presentation Tables, where records can be composed of any data from any source in the system.

Rules

Usage
  1. Rows in the table MUST be of the same structure.
Interaction
  1. View Controls used here MUST only affect the table itself.
  2. Clicking the Expand Glyph MUST only expand the row. It MUST NOT trigger any other action.
Accessibility
  1. The expandable content, especially the contained buttons, MUST be accessible by only using the keyboard.

Example 1: Base1

Presentation Table with Alignments

<?php
 
declare(strict_types=1);
 
namespace ILIAS\UI\examples\Table\Presentation;
 
/**
 * You can also leave out "further fields" and use alignments instead,
 * add one or more Blocks and Layouts to the content of the row and add an leading image.
 */
function base1()
{
    global $DIC;
    $ui_factory = $DIC->ui()->factory();
    $renderer = $DIC->ui()->renderer();
    $tpl = $DIC['tpl'];
    $target = $DIC->http()->request()->getRequestTarget();
    $refinery = $DIC->refinery();
    $request_wrapper = $DIC->http()->wrapper()->query();
 
    $tpl->addCss('src/UI/examples/Table/Presentation/presentation_alignment_example.css');
 
    //example data
    $data = included_data1();
 
    //build viewcontrols
    $aria_label = "filter entries";
    $active_view_control = 'Alle';
    $actions = [
        "Alle" => $target . '&all=1',
        "Mehr als 5 Antworten" => $target . '&all=0'
    ];
    if ($request_wrapper->has('all') && $request_wrapper->retrieve('all', $refinery->kindlyTo()->int()) === 0) {
        $data = [array_shift($data)];
        $active_view_control = 'Mehr als 5 Antworten';
    }
    $view_controls = array(
        $ui_factory->viewControl()->mode($actions, $aria_label)->withActive($active_view_control)
    );
 
    //build an example modal
    $modal = $ui_factory->modal()->interruptive('zur Frage', 'This is just an example', '#')
        ->withActionButtonLabel('Go');
 
    $mapping_closure = function ($row, $record, $ui_factory, $environment) use ($modal) {
        return $row
        ->withHeadline($record['question_title'])
        ->withLeadingSymbol(
            $ui_factory->symbol()->icon()->custom('templates/default/images/standard/icon_ques.svg', '')
        )
        ->withSubheadline($record['question_txt'])
        ->withImportantFields(
            array(
                $record['type'],
                'Beantwortet: ' => $record['stats']['total'],
                'Häufigste Antwort: ' => $record['answers'][$record['stats']['most_common']]['title']
            )
        )
        ->withContent(
            $ui_factory->layout()->alignment()->horizontal()->dynamicallyDistributed(
                $ui_factory->layout()->alignment()->vertical(
                    $ui_factory->listing()->descriptive([
                        'Werte' => $environment['totals']($record['answers'])
                    ]),
                    $ui_factory->listing()->descriptive([
                        'Chart' => $environment['chart']($record['answers'])
                    ])
                ),
                $ui_factory->listing()->descriptive([
                    '' => $environment['stats']($record)
                ])
            )
        )
        ->withAction(
            $ui_factory->button()->standard('zur Frage', '#')
                ->withOnClick($modal->getShowSignal())
        );
    };
 
    $ptable = $ui_factory->table()->presentation(
        'Presentation Table with Alignments', //title
        $view_controls,
        $mapping_closure
    )
    ->withEnvironment(environment());
 
 
    //apply data to table and render
    return $renderer->render([
        $modal,
        $ptable->withData($data)
    ]);
}
 
function environment()
{
    $totals = function ($answers) {
        $ret = '<div class="example_block content"><table>';
        $ret .= '<tr><td></td>'
            . '<td>Amount</td>'
            . '<td style="padding-left: 10px;">Proportion</td></tr>';
 
        foreach ($answers as $answer) {
            $ret .= '<tr>'
                . '<td style="padding-right: 10px;">' . $answer['title'] . '</td>'
                . '<td style="text-align:right">' . $answer['amount'] . '</td>'
                . '<td style="text-align:right">' . $answer['proportion'] . '%</td>'
                . '</tr>';
        }
 
        $ret .= '</table></div>';
        return $ret;
    };
 
    $chart = function ($answers) {
        $ret = '<div class="example_block content"><table style="width:100%">';
        foreach ($answers as $answer) {
            $ret .= '<tr style="border-bottom: 1px solid black;">'
                . '<td style="width: 200px;">'
                . $answer['title']
                . '</td><td>'
                . '<div style="background-color:grey; height:20px; width:' . $answer['proportion'] . '%;"></div>'
                . '</td></tr>';
        }
        $ret .= '</table></div>';
        return $ret;
    };
 
    $stats = function ($answers) {
        global $DIC;
        $ui_factory = $DIC->ui()->factory();
        $ui_renderer = $DIC->ui()->renderer();
 
        $icon = $ui_factory->symbol()->icon()->custom('templates/default/images/standard/icon_ques.svg', '');
 
        $ret = '<div class="example_block stats">';
        $ret .= '<h5>' . $ui_renderer->render($icon) . ' ' . $answers['type'] . '</h5>';
        $ret .= '<span class="c-stats--title">Beantwortet:</span> '
            . $answers['stats']['total'] . '<br>'
            . '<span class="c-stats--title">Übersprungen:</span> '
            . $answers['stats']['skipped'] . '<br>'
            . '<span class="c-stats--title">Häufigste Antwort:</span> '
            . $answers['answers'][$answers['stats']['most_common']]['title'] . '<br>'
            . '<span class="c-stats--title">Anzahl Häufigste:</span> '
            . $answers['stats']['most_common_total'] . '<br>'
            . '<span class="c-stats--title">Median:</span> '
            . $answers['answers'][$answers['stats']['median']]['title'];
        $ret .= '</div>';
        return $ret;
    };
 
    return array(
        'totals' => $totals,
        'chart' => $chart,
        'stats' => $stats
    );
}
 
function included_data1()
{
    return array(
        array(
            'type' => 'Single Choice Frage',
            'question_title' => 'Belastbarkeit',
            'question_txt' => 'Wie ausgeprägt ist die Belastbarkeit des / der Auszubildenden?',
            'answers' => array(
                array('title' => 'weniger ausgeprägt', 'amount' => 2, 'proportion' => 20),
                array('title' => 'teilweise ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'ausgeprägt', 'amount' => 6, 'proportion' => 60),
                array('title' => 'deutlich ausgeprägt', 'amount' => 1, 'proportion' => 10),
                array('title' => 'stark ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'sehr stark ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'übermäßig ausgeprägt', 'amount' => 1, 'proportion' => 10)
            ),
            'stats' => array(
                'total' => 10,
                'skipped' => 2,
                'most_common' => 2,
                'most_common_total' => 6,
                'median' => 2,
            )
        ),
 
        array(
            'type' => 'Single Choice Frage',
            'question_title' => 'Dialogfähigkeit, Kundenorientierung, Beratungsfähigkeit',
            'question_txt' => 'Wie ausgeprägt ist die Dialogfähigkeit, Kundenorientierung und Beratungsfähigkeit des / der Auszubildenden?',
            'answers' => array(
                array('title' => 'weniger ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'teilweise ausgeprägt', 'amount' => 1, 'proportion' => 100),
                array('title' => 'ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'deutlich ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'stark ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'sehr stark ausgeprägt', 'amount' => 0, 'proportion' => 0),
                array('title' => 'übermäßig ausgeprägt', 'amount' => 0, 'proportion' => 0)
            ),
            'stats' => array(
                'total' => 1,
                'skipped' => 0,
                'most_common' => 1,
                'most_common_total' => 1,
                'median' => 1,
            )
        ),
    );
}
 

Example 2: Base

Presentation Table

<?php
 
declare(strict_types=1);
 
namespace ILIAS\UI\examples\Table\Presentation;
 
function base()
{
    global $DIC;
    $f = $DIC->ui()->factory();
    $renderer = $DIC->ui()->renderer();
    $target = $DIC->http()->request()->getRequestTarget();
    $refinery = $DIC->refinery();
    $request_wrapper = $DIC->http()->wrapper()->query();
 
    //example data as from an assoc-query, list of arrays
    $active_view_control = 'All';
    $data = included_data();
    if ($request_wrapper->has('upcoming') && $request_wrapper->retrieve('upcoming', $refinery->kindlyTo()->int()) === 1) {
        $data = [array_shift($data)];
        $active_view_control = 'Upcoming events';
    }
 
    //build viewcontrols
    $actions = [
        "All" => $target . '&upcoming=0',
        "Upcoming events" => $target . '&upcoming=1'
    ];
    $aria_label = "filter entries";
    $view_controls = array(
        $f->viewControl()->mode($actions, $aria_label)->withActive($active_view_control)
    );
 
    //build an example modal
    $modal = $f->modal()->interruptive('Book Course', 'This is just an example', '#')
        ->withActionButtonLabel('Do Something');
 
    //build table
    $ptable = $f->table()->presentation(
        'Presentation Table', //title
        $view_controls,
        function ($row, $record, $ui_factory, $environment) use ($modal) { //mapping-closure
            return $row
                ->withHeadline($record['title'])
                ->withSubheadline($record['type'])
                ->withImportantFields(
                    array(
                        $record['begin_date'],
                        $record['location'],
                        'Available Slots: ' => $record['bookings_available']
                    )
                )
 
                ->withContent(
                    $ui_factory->listing()->descriptive(
                        array(
                            'Targetgroup' => $record['target_group'],
                            'Goals' => $record['goals'],
                            'Topics' => $record['topics']
                        )
                    )
                )
 
                ->withFurtherFieldsHeadline('Detailed Information')
                ->withFurtherFields(
                    array(
                        'Location: ' => $record['location'],
                        $record['address'],
                        'Date: ' => $record['date'],
                        'Available Slots: ' => $record['bookings_available'],
                        'Fee: ' => $record['fee']
                    )
                )
                ->withAction(
                    $ui_factory->button()
                        ->standard('book course', '')
                        ->withOnClick($modal->getShowSignal())
                );
        }
    );
 
 
 
    //apply data to table and render
    return $renderer->render([
        $modal,
        $ptable->withData($data)
    ]);
}
 
function included_data()
{
    return [
        [
            'title' => 'Online Presentation of some Insurance Topic',
            'type' => 'Webinar',
            'begin_date' => (new \DateTime())->modify('+1 day')->format('d.m.Y'),
            'bookings_available' => '3',
            'target_group' => 'Employees, Field Service',
            'goals' => 'Lorem Ipsum....',
            'topics' => '<ul><li>Tranportations</li><li>Europapolice</li></ul>',
            'date' => (new \DateTime())->modify('+1 day')->format('d.m.Y')
                . ' - '
                . (new \DateTime())->modify('+2 day')->format('d.m.Y'),
            'location' => 'Hamburg',
            'address' => 'Hauptstraße 123',
            'fee' => '380 €'
        ],
        [
            'title' => 'Workshop: Life Insurance 2017',
            'type' => 'Face 2 Face',
            'begin_date' => '12.12.2017',
            'bookings_available' => '12',
            'target_group' => 'Agencies, Field Service',
            'goals' => 'Life insurance (or life assurance, especially in the Commonwealth   of Nations), is a contract between an insurance policy holder and an insurer or assurer, where the insurer promises to pay a designated beneficiary a sum of money (the benefit) in exchange for a premium, upon the death of an insured person (often the policy holder). Depending on the contract, other events such as terminal illness or critical illness can also trigger payment. The policy holder typically pays a premium, either regularly or as one lump sum. Other expenses (such as funeral expenses) can also be included in the benefits.',
            'topics' => 'Life-based contracts tend to fall into two major categories:
                        <ul><li>Protection policies – designed to provide a benefit, typically a lump sum payment, in the event of a specified occurrence. A common form - more common in years past - of a protection policy design is term insurance.</li>
                        <li>Investment policies – the main objective of these policies is to facilitate the growth of capital by regular or single premiums. Common forms (in the U.S.) are whole life, universal life, and variable life policies.</li></ul>',
            'date' => '12.12.2017 - 14.12.2017',
            'location' => 'Cologne',
            'address' => 'Holiday Inn, Am Dom 12, 50667 Köln',
            'fee' => '500 €'
        ],
        [
            'title' => 'Basics: Preparation for Seminars',
            'type' => 'Online Training',
            'begin_date' => '-',
            'bookings_available' => 'unlimited',
            'target_group' => 'All',
            'goals' => '',
            'topics' => '',
            'date' => '-',
            'location' => 'online',
            'address' => '',
            'fee' => '-'
        ]
    ];
}
 

Example 3: Without data

Empty Presentation Table

No records
<?php
 
declare(strict_types=1);
 
namespace ILIAS\UI\examples\Table\Presentation;
 
use ILIAS\UI\Component\Table\PresentationRow;
use ILIAS\UI\Factory;
 
/**
 * Example showing a presentation table without any data and hence no entries, which
 * will automatically display an according message.
 */
function without_data(): string
{
    global $DIC;
 
    $factory = $DIC->ui()->factory();
    $renderer = $DIC->ui()->renderer();
 
    $minimal_mapping = static fn(
        PresentationRow $row,
        mixed $record,
        Factory $ui_factory,
        mixed $environment
    ): PresentationRow => $row;
 
    $table = $factory->table()->presentation(
        'Empty Presentation Table',
        [$factory->viewControl()->mode(['All' => '#'], '')],
        $minimal_mapping
    );
 
    // Note: this is an optional call, it should merely demonstrate that we have
    // an empty table.
    $table->withData([]);
 
    return $renderer->render($table);
}
 

Relations

Parents
  1. UIComponent
  2. Table