Skip to content

Commit 0ad1eac

Browse files
authored
Merge pull request #522 from WoltLab/6.2-list-views
Document list views
2 parents 1246891 + 49eb198 commit 0ad1eac

File tree

2 files changed

+279
-0
lines changed

2 files changed

+279
-0
lines changed

docs/php/api/list_views.md

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# List Views
2+
3+
List views are a generic solution for the creation of listings that are ubiquitous in the software.
4+
In contrast to [grid views](grid_views.md), list views do not specify a particular layout.
5+
The developer must specify a custom template that takes care of the rendering of the entries.
6+
A list view takes care of sorting, filtering and pagination, and ensure that a lot of boilerplating becomes obsolete.
7+
8+
The implementation essentially offers the following advantages:
9+
1. A uniform appearance and usability for the user.
10+
2. An easy way for developers to create their own list views.
11+
3. An easy way for developers to extend existing list views using plugins.
12+
13+
## Usage
14+
15+
### AbstractListView
16+
17+
List views obtain their data from a database object list and display it using custom template.
18+
19+
Example:
20+
21+
```php
22+
<?php
23+
24+
namespace wcf\system\listView\user;
25+
26+
use wcf\data\DatabaseObjectList;
27+
use wcf\system\listView\AbstractListView;
28+
use wcf\system\WCF;
29+
30+
/**
31+
* @extends AbstractListView<Example, ExampleList>
32+
*/
33+
class ExampleListView extends AbstractListView
34+
{
35+
#[\Override]
36+
protected function createObjectList(): DatabaseObjectList
37+
{
38+
return new ExampleList();
39+
}
40+
41+
#[\Override]
42+
public function isAccessible(): bool
43+
{
44+
return true;
45+
}
46+
47+
#[\Override]
48+
public function renderItems(): string
49+
{
50+
return WCF::getTPL()->render('wcf', 'exampleListItems', ['view' => $this]);
51+
}
52+
}
53+
```
54+
55+
Example `exampleListItems.tpl`:
56+
57+
```smarty
58+
{foreach from=$view->getItems() item='item'}
59+
<div class="listView__item" data-object-id="{$item->getObjectID()}">
60+
<h2>{$item->getTitle()}</h2>
61+
</div>
62+
{/foreach}
63+
```
64+
65+
### AbstractListViewPage
66+
67+
A list view can be displayed on a page by inheriting from `AbstractListViewPage`.
68+
69+
Example:
70+
71+
```php
72+
<?php
73+
74+
namespace wcf\page;
75+
76+
use wcf\system\listView\user\ArticleListView;
77+
78+
/**
79+
* @extends AbstractListViewPage<ExampleListView>
80+
*/
81+
class ExampleListPage extends AbstractListViewPage
82+
{
83+
#[\Override]
84+
protected function createListView(): ExampleListView
85+
{
86+
return new ExampleListView();
87+
}
88+
}
89+
```
90+
91+
```smarty
92+
{include file='header'}
93+
94+
<div class="section">
95+
{unsafe:$listView->render()}
96+
</div>
97+
98+
{include file='footer'}
99+
```
100+
101+
## Sorting
102+
103+
The `addAvailableSortFields` method allows you to define columns that the user can use to sort the list.
104+
The columns must exist in the linked database object list.
105+
106+
```php
107+
class ExampleListView extends AbstractListView
108+
{
109+
public function __construct() {
110+
$this->addAvailableSortFields([
111+
new ListViewSortField('time', 'wcf.global.date'),
112+
new ListViewSortField('title', 'wcf.global.title'),
113+
]);
114+
}
115+
}
116+
```
117+
118+
By default, sorting is based on the `id` (first parameter) of the specified sort field.
119+
Optionally, you can specify the name of an alternative database column to be used for sorting instead:
120+
121+
```php
122+
new ListViewSortField('title', 'wcf.global.title', 'table_alias.columnName'),
123+
```
124+
125+
The default sorting can be defined after the configuration of the sort fields has been defined:
126+
127+
```php
128+
class ExampleListView extends AbstractListView
129+
{
130+
public function __construct()
131+
{
132+
$this->addAvailableSortFields([
133+
new ListViewSortField('time', 'wcf.global.date'),
134+
new ListViewSortField('title', 'wcf.global.title'),
135+
]);
136+
137+
$this->setSortField('title');
138+
$this->setSortOrder('ASC');
139+
}
140+
}
141+
```
142+
143+
## Filtering
144+
145+
Filters can be defined for columns so that the user has the option to filter by the content of a column.
146+
147+
```php
148+
class ExampleListView extends AbstractListView
149+
{
150+
public function __construct()
151+
{
152+
$this->addAvailableFilters([
153+
new TextFilter('title', 'wcf.global.title'),
154+
]);
155+
}
156+
}
157+
```
158+
159+
## Customization
160+
161+
### Number of Items
162+
163+
By default, list views use a pagination that shows 20 items per page. You can set a custom number of items per page:
164+
165+
```php
166+
class ExampleListView extends AbstractListView
167+
{
168+
public function __construct()
169+
{
170+
$this->setItemsPerPage(50);
171+
}
172+
}
173+
```
174+
175+
There are some cases where only a list with a fixed number of items is required, for example, showcasing the 10 latests items.
176+
177+
```php
178+
class ExampleListView extends AbstractListView
179+
{
180+
public function __construct()
181+
{
182+
$this->fixedNumberOfItems(10);
183+
}
184+
}
185+
```
186+
187+
### CSS Class Names
188+
189+
Optionally, a CSS class can be set on the surrounding HTML element:
190+
191+
```php
192+
class ExampleListView extends AbstractListView
193+
{
194+
public function __construct()
195+
{
196+
$this->setCssClassName('exampleList');
197+
}
198+
}
199+
```
200+
201+
### Additional Parameters
202+
203+
A list view can be provided with additional parameters, e.g. to filter them by a specific category:
204+
205+
```php
206+
class ExampleListView extends AbstractListView
207+
{
208+
public function __construct(public readonly int $categoryID)
209+
{
210+
parent::__construct();
211+
}
212+
213+
#[\Override]
214+
protected function createObjectList(): DatabaseObjectList
215+
{
216+
$list = new ExampleList();
217+
$list->getConditionBuilder()->add('categoryID = ?', [$this->categoryID]);
218+
219+
return $list;
220+
}
221+
222+
#[\Override]
223+
public function getParameters(): array
224+
{
225+
return ['categoryID' => $this->categoryID];
226+
}
227+
}
228+
```
229+
230+
```php
231+
class ExampleListPage extends AbstractListViewPage
232+
{
233+
public int $categoryID = 0;
234+
235+
#[\Override]
236+
public function readParameters()
237+
{
238+
if (isset($_REQUEST['categoryID'])) {
239+
$this->categoryID = \intval($_REQUEST['categoryID']);
240+
}
241+
242+
parent::readParameters();
243+
}
244+
245+
#[\Override]
246+
protected function createListView(): AbstractListView
247+
{
248+
return new ExampleListView($this->categoryID);
249+
}
250+
251+
#[\Override]
252+
protected function initListView(): void
253+
{
254+
parent::initListView();
255+
256+
$this->listView->setBaseUrl(LinkHandler::getInstance()->getControllerLink(static::class, [
257+
'categoryID' => $this->categoryID,
258+
]));
259+
}
260+
}
261+
```
262+
263+
## Events
264+
265+
Existing list views can be modified using events.
266+
267+
Example of adding an additional sort field:
268+
269+
```php
270+
$eventHandler->register(
271+
\wcf\event\listView\user\ArticleListViewInitialized::class,
272+
static function (\wcf\event\listView\user\ArticleListViewInitialized $event) {
273+
$event->listView->addAvailableSortField(
274+
new ListViewSortField('example', 'wcf.global.example'),
275+
);
276+
}
277+
);
278+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ nav:
4040
- 'Validation and Data': 'php/api/form_builder/validation_data.md'
4141
- 'Dependencies': 'php/api/form_builder/dependencies.md'
4242
- 'Grid Views': 'php/api/grid_views.md'
43+
- 'List Views': 'php/api/list_views.md'
4344
- 'Package Installation Plugins': 'php/api/package_installation_plugins.md'
4445
- 'RPC API': 'php/api/rpc_api.md'
4546
- 'User Activity Events': 'php/api/user_activity_events.md'

0 commit comments

Comments
 (0)