diff --git a/docs/php/api/grid_views.md b/docs/php/api/grid_views.md new file mode 100644 index 000000000..883dc826e --- /dev/null +++ b/docs/php/api/grid_views.md @@ -0,0 +1,353 @@ +# Grid Views + +Grid views are a generic solution for the creation of listings that are ubiquitous in the software. +In addition to rendering, the grid view also take care of sorting, filtering and pagination, and ensure that a lot of boilerplating becomes obsolete. + +The implementation essentially offers the following advantages: +1. A uniform appearance and usability for the user. +2. An easy way for developers to create their own grid views. +3. An easy way for developers to extend existing grid views using plugins. + +## Usage + +### AbstractGridView + +Grid views obtain their data from a database object list and display it using a defined column configuration. + +Example: + +```php +addColumns([ + GridViewColumn::for('id') + ->label('wcf.global.objectID') + ->renderer(new ObjectIdColumnRenderer()) + ->sortable(), + GridViewColumn::for('title') + ->label('wcf.global.title') + ->sortable() + ->titleColumn() + ]); + } + + #[\Override] + public function isAccessible(): bool + { + return true; + } + + #[\Override] + protected function createObjectList(): DatabaseObjectList + { + return new ExampleDatabaseObjectList(); + } +} +``` + +### AbstractGridViewPage + +A grid view can be displayed on a page by inheriting from `AbstractGridViewPage`. + +Example: + +```php + + {unsafe:$gridView->render()} + + +{include file='footer'} +``` + +## Columns + +Columns can be created using the `GridViewColumn::for` method. This expects a unique string as a parameter, which is equivalent to the corresponding key in the data source. + +The `label` method can be used to give the column a human readable label. + +Example: + +```php +final class FooGridView extends AbstractGridView +{ + public function __construct() + { + $this->addColumns([ + GridViewColumn::for('id') + ->label('wcf.global.objectID'), + GridViewColumn::for('name') + ->label('wcf.global.name'), + ]); + } +} +``` + +### Renderer + +Renderers can be applied to columns to format the output. A column can have multiple renderers. The renderers are applied in the order in which they were set. + +```php +GridViewColumn::for('foo') + ->renderer([ + new FooColumnRenderer(), + new BarColumnRenderer(), + ]) +``` + +#### CategoryColumnRenderer + +`CategoryColumnRenderer` can be set to columns that contain the ID of categories. This results in the name of the category being output. + +#### CurrencyColumnRenderer + +`CurrencyColumnRenderer` formats the content of a column as a currency. Expects the content of the column to be a decimal. + +Example: + +```php +GridViewColumn::for('foo') + ->renderer(new CurrencyColumnRenderer('EUR')) +``` + +#### DefaultColumnRenderer + +The `DefaultColumnRenderer` is implicitly applied to all columns unless one ore more renderers have been explicitly set. + +#### EmailColumnRenderer + +`EmailColumnRenderer` formats the content of the column as an email address. + +#### FilesizeColumnRenderer + +`FilesizeColumnRenderer` formats the content of the column as a file size. + +#### IpAddressColumnRenderer + +`IpAddressColumnRenderer` outputs the value by attempting to interpret it as IPv4 if possible, otherwise shows the IPv6 address. + +#### LinkColumnRenderer + +`LinkColumnRenderer` allows the setting of a link to a column. + +Example: + +```php +GridViewColumn::for('foo') + ->renderer(new LinkColumnRenderer(FooEditForm::class)) +``` + +#### NumberColumnRenderer + +`NumberColumnRenderer` formats the content of a column as a number using `StringUtil::formatNumeric()`. + +#### ObjectIdColumnRenderer + +`ObjectIdColumnRenderer` formats the content of a column as an object id. + +#### PhraseColumnRenderer + +`PhraseColumnRenderer` attempts to evaluate the value as a phrase and outputs it as plain text otherwise. + +#### TimeColumnRenderer + +`TimeColumnRenderer` renders a unix timestamp into a human readable format. + +#### TruncatedTextColumnRenderer + +`TruncatedTextColumnRenderer` truncates the content of a column to a length of 80 characters (default value). + +#### UserColumnRenderer + +`UserColumnRenderer` formats the content of a column as a user. + +#### UserLinkColumnRenderer + +`UserLinkColumnRenderer` is a combination of the `UserColumnRenderer` and the `LinkColumnRenderer`. + +Example: + +```php +GridViewColumn::for('foo') + ->renderer(new UserLinkColumnRenderer(FooEditForm::class)) +``` + +### Custom Renderer + +If necessary, you can define your own renderers: + +```php +GridViewColumn::for('id') + ->renderer([ + new class extends DefaultColumnRenderer { + public function render(mixed $value, DatabaseObject $row): string + { + return 'foo: ' . $value; + } + }, + ]), +``` + +### Row Link + +A row link applies a link to every column in the grid. + +```php +final class FooGridView extends AbstractGridView +{ + public function __construct() + { + $this->addRowLink(new GridViewRowLink(FooEditForm::class)); + } +} +``` + +The constructor supports 3 optional parameters: +1. `string $controllerClass`: The controller to which the link should refer. +2. `array $parameters`: Additional parameters for the controller. +3. `string $cssClass`: CSS class for the link. + +### Sorting + +Columns can be marked as sortable so that the user has the option of sorting according to the content of the column. + +```php +GridViewColumn::for('foo') + ->sortable() +``` + +By default, sorting is based on the `id` of the column. +Optionally, you can specify the name of an alternative database column to be used for sorting instead: + +```php +GridViewColumn::for('foo') + ->sortable(sortByDatabaseColumn: "table_alias.columnName") +``` + +The default sorting can be defined after the column configuration has been defined: + +```php +final class FooGridView extends AbstractGridView +{ + public function __construct() + { + GridViewColumn::for('title') + ->sortable(); + + $this->setSortField('title'); + $this->setSortOrder('ASC'); + } +} +``` + +### Filtering + +Filters can be defined for columns so that the user has the option to filter by the content of a column. + +```php +GridViewColumn::for('foo') + ->filter(new FooFilter()) +``` + +#### BooleanFilter + +`BooleanFilter` is a filter for columns that contain boolean values (`1` or `0`). + +#### CategoryFilter + +`CategoryFilter` is a filter for columns that contain category ids. + +```php +GridViewColumn::for('categoryID') + ->filter(new CategoryFilter((new CategoryNodeTree('identifier'))->getIterator())) +``` + +#### I18nTextFilter + +`I18nTextFilter` is a filter for text columns that are using i18n phrases. + +#### IpAddressFilter + +`IpAddressFilter` is a filter for columns that contain IPv6 addresses, allowing the user to enter addresses in the IPv4 format too. + +#### NumericFilter + +`NumericFilter` is a filter for columns that contain numeric values. + +#### ObjectIdFilter + +`ObjectIdFilter` is a filter for columns that contain object ids. + +#### SelectFilter + +`SelectFilter` allows a column to be filtered on the basis of a select dropdown. + +```php +GridViewColumn::for('foo') + ->filter(new SelectFilter([ + 1 => 'value 1', + 0 => 'value 0', + ])); +``` + +#### TextFilter + +`TextFilter` is a filter for text columns. + +#### TimeFilter + +`TimeFilter` is a filter for columns that contain unix timestamps. + +#### UserFilter + +`UserFilter` is a filter for columns that contain user ids. + +### Events + +Existing grid views can be modified using events. + +Example of adding an additional column: + +```php +$eventHandler->register( + \wcf\event\gridView\UserRankGridViewInitialized::class, + static function (\wcf\event\gridView\UserRankGridViewInitialized $event) { + $event->gridView->addColumnBefore( + GridViewColumn::for('hideTitle') + ->label('hideTitle') + ->renderer(new NumberColumnRenderer()) + ->sortable(), + 'requiredPoints' + ); + } +); +``` diff --git a/mkdocs.yml b/mkdocs.yml index 9b8deae6e..f77b2c553 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -39,6 +39,7 @@ nav: - 'Fields': 'php/api/form_builder/form_fields.md' - 'Validation and Data': 'php/api/form_builder/validation_data.md' - 'Dependencies': 'php/api/form_builder/dependencies.md' + - 'Grid Views': 'php/api/grid_views.md' - 'Package Installation Plugins': 'php/api/package_installation_plugins.md' - 'RPC API': 'php/api/rpc_api.md' - 'User Activity Events': 'php/api/user_activity_events.md'