diff --git a/docs/book/v7/how-to/using-simple-tables.md b/docs/book/v7/how-to/using-simple-tables.md new file mode 100644 index 0000000..2a87ba2 --- /dev/null +++ b/docs/book/v7/how-to/using-simple-tables.md @@ -0,0 +1,205 @@ +# Use simple tables + +## Summary + +This page explains how to build a list page as a simple table, with sortable columns, row selection and column visibility that is remembered for each admin. + +## Details + +Simple tables are used by the list pages of Dotkernel Admin, such as the lists of admins, admin logins and users. +Each table is made of these parts: + +- a Twig template that renders the table, using the `sortableColumn` macro from `@partial/macros.html.twig` +- the `table_settings.js` script, which shows or hides columns and enables the edit and delete buttons +- the `Setting` entity, which stores the selected columns for each admin and table +- two routes that read and write the setting: `setting::view-setting` (`GET /{identifier}`) and `setting::store-setting` (`POST /{identifier}`) + +When the page loads, `table_settings.js` requests the saved column selection, applies it, then displays the table. +Whenever the admin toggles a column, the script saves the new selection. +If no selection was saved yet, all columns are displayed. + +The examples below build a list page for books. +For a complete module, see [Creating a book module using DotMaker](../tutorials/create-book-module-via-dot-maker.md). + +## Create a simple table + +Creating a simple table requires four steps: + +- add a setting identifier +- send the identifier to the template +- render the table +- load the scripts + +### Add a setting identifier + +Each table stores its selected columns under its own identifier. +Open `src/Core/src/Setting/src/Enum/SettingIdentifierEnum.php` and add a new case: + +```php +case IdentifierTableBookListSelectedColumns = 'table_book_list_selected_columns'; +``` + +The `identifier` column of the `settings` table is a database `ENUM`, so the new case requires a migration. +Generate it, check that it alters the `settings.identifier` column, then run it: + +```shell +php ./vendor/bin/doctrine-migrations diff +php ./vendor/bin/doctrine-migrations migrate +``` + +See [Create Database Migrations](creating-migrations.md) for more details. + +### Send the identifier to the template + +In the handler that renders the list, send the identifier to the template: + +```php +return new HtmlResponse( + $this->template->render('book::list-book', [ + 'pagination' => $this->bookService->getBooks($request->getQueryParams()), + 'identifier' => SettingIdentifierEnum::IdentifierTableBookListSelectedColumns->value, + ]) +); +``` + +### Render the table + +In the template, import the macro and render the column selector and the table. +The example below shows only the basic listing. +The full template, with the add, edit and delete buttons and modals, pagination and the remaining columns, is in [Creating a book module using DotMaker](../tutorials/create-book-module-via-dot-maker.md). + +```html +{% from '@partial/macros.html.twig' import sortableColumn %} + +{% extends '@layout/default.html.twig' %} + +{% block title %}Manage books{% endblock %} + +{% block content %} +
+

Manage books

+
+
+
+ + + + + + + + + + + {% for book in pagination.items %} + + + + + + + {% endfor %} + + + {% if pagination.isOutOfBounds %} + + {% endif %} +
+
+
+
+{% endblock %} +``` + +Things to note: + +- the table is hidden with `style="display: none;"`, the script displays it after applying the saved selection +- the `#column-selector` list is empty, the script fills it with one checkbox for each sortable column +- the first column holds the row checkbox and has no `sortableColumn`, so it cannot be hidden + +### Load the scripts + +At the end of the template, define the three variables that `table_settings.js` requires, then load the script: + +```html +{% block javascript %} +{{ parent() }} + + +{% endblock %} +``` + +If any of the three variables is missing, the script logs an error in the browser console and does nothing. +Any page specific script, such as `book.js`, is loaded the same way, using `type="module"`. +It must be registered in the `entries` object of `vite.config.js` and built, see [Use NPM Commands](npm_commands.md). + +## Name the columns + +The `sortableColumn` macro receives the sort key as its fourth argument. +It adds the `table-column` class to the header link and sets its `data-column` attribute to the sort key, with dots replaced by dashes. +The script hides and shows a column by the class `column-`, so every `` and `` of that column must use the same class: + +| Sort key | `data-column` | Class | +|--------------------|--------------------|---------------------------| +| `user.identity` | `user-identity` | `column-user-identity` | +| `detail.firstName` | `detail-firstName` | `column-detail-firstName` | +| `book.releaseDate` | `book-releaseDate` | `column-book-releaseDate` | + +## Edit and delete buttons + +`table_settings.js` also handles row selection: + +- clicking a row (`.table-row`) toggles its checkbox +- the buttons with the ids `btn-edit-resource` and `btn-delete-resource` are enabled only while exactly one `.ui-checkbox` is checked + +The URLs of the selected row are read from the `data-edit-url` and `data-delete-url` attributes of the checked box. +Opening the modals that use them is done by the page specific script, see the `_book.js` file in [Creating a book module using DotMaker](../tutorials/create-book-module-via-dot-maker.md). + +## FAQ + +**Q: Why is a column always displayed, even if I untick it in the column selector?** + +A: The `` or `` class does not match the column's `data-column` value. +Check that every cell of that column uses `column-` followed by the sort key with dots replaced by dashes. + +**Q: Why is the column selector empty?** + +A: The selector is built from the elements with the `table-column` class. +Make sure the headers use the `sortableColumn` macro and that the template contains an empty `