Tento článek patří do seriálu Jak na DataTables. Ostatní články seriálu:
- Vlastní filtry s DataTables a AJAXem
- Vlastní vykreslení buňky v DataTables s AJAXem
DataTables je JavaSriptová knihovna, aktuálně stále vyžadující jQuery, pro tvorbu interaktivních tabulek s mnoha pluginy. Možnosti nastavení jsou obrovské a osobně jej využívám v systému pro SunOutdoor. V částech, kde se očekávají jednotky až nižší desítky záznamů používám client-side rendering. Tedy vše pošlu na klienta a DataTables se starají o seřazování i vyhledávaní. V tomto případě jsou vlastní filtry jednodušší a v dokumentaci existuje ukázka včetně kódů.
V administraci, kde jsou tisíce až desetitisíce záznamů, už není vhodné vypisovat vše. Lepší je provést vyhledání a seřazení na serveru a odeslat jen zlomek záznamů. Hodnota z integrovaného vyhledávaní je automaticky obsažena v XHR requestu, který se posílá na server. Následující návod popisuje, jak do XHR requestu i do tabulky přidat vlastní filtry.

Přidání vstupního pole
V client-side ukázce v odkazu výše jsou nová pole nad tabulkou. To se mi ale příliš nezamlouvá z UX pohledu. Proto je níže popsán způsob, jak pole vložit vedle vyhledávaní tak, jak je znázorněno na obrázku. V HTML šabloně je pole pro Archív nad tabulkou, aby se již ze serveru naplnilo daty.
<label class="js-archiveFilter">
Archív<select class="form-control js-archiveFilterSelect">
<option value="">Aktuální</option>
<optgroup label="Ročník">
<option value="2020">2020</option>
<option value="2019">2019</option>
</optgroup>
</select>
</label>
<table class="table table-striped" data-table>
<thead>
<tr>
<th>Jméno</th>
<th>Datum konání</th>
<th>Způsob platby</th>
<th>Zbývá uhradit</th>
<th style="width: 10%">Akce</th>
</tr>
</thead>
<tbody><!-- Vyplní se automaticky pomocí odpovědi ze serveru --></tbody>
</table>
Následně se pomocí JavaScriptu pole s výběrem Archívu přesune přímo do tabulky a propojí se tak, aby při změně došlo k překreslení a tedy i stažení nového obsahu ze serveru.
const predefinedDom = {
inCard:
"<'px-3 pt-3 datatable_header_wrapper'<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>>" +
"<'row'<'col-sm-12'tr>>" +
"<'px-2 pb-3 small datatable_footer_wrapper'<'row'<'col-12'i><'col-12'p>>>",
// Obsahuje navíc třídu withArchive a větší sloupec u wrapperu vyhledávání
inCardWithArchive:
"<'px-3 pt-3 datatable_header_wrapper'<'row'<'col-sm-12 col-md-4'l><'col-sm-12 col-md-8 withArchive'f>>>" +
"<'row'<'col-sm-12'tr>>" +
"<'px-2 pb-3 small datatable_footer_wrapper'<'row'<'col-12'i><'col-12'p>>>",
};
let usedDom = predefinedDom.inCard;
let instance = null;
let ajaxData = null;
if (showFilter === true) {
$(document)
.one('preInit.dt', function(){ // Před inicializací se přesune pole
let filter = $('.js-archiveFilter');
filter.prependTo('.withArchive .dataTables_filter');
// Při změně je nutné zavolat překreslení tabulky, což načte čerstvá data
filter.find('select').addClass('form-control-sm').on('change',function () {
instance.draw();
});
})
.on('stateSaveParams.dt', function (e, settings, data) {
// Při ukládání aktuálního stavu (stateSave) do local/session storage se uloží také stav archívu
data.archive = { year: $('.js-archiveFilterSelect').val() };
})
.on('stateLoadParams.dt', function (e, settings, data) {
// Při načítání aktuálního stavu (stateSave) z local/session storage se načte také stav archívu
if (data.archive && data.archive.year) {
$(".js-archiveFilterSelect option[value='" + data.archive.year + "']").prop('selected', true);
}
});
usedDom = predefinedDom.inCardWithArchive; // Při použití archívu se přidá DOM s extra třídou
ajaxData = function (data) {
// Vždy před odesláním XHR requestu se přidá aktuální hodnota z filtru archív
data.archive = $('.js-archiveFilterSelect').val();
};
}
instance = $('table[data-table]').DataTable({
stateSave: true, // Zapne ukládání aktuální strany, vyhledávání i archívu do local/session storage
dom: usedDom,
ajax: {
url: "/path/to/backend/api",
data: ajaxData,
},
serverSide: true, // Zapne načítání dat ze serveru definováno v ajax.url
});
XHR Request a Laravel
Při změně počtu zobrazovaných záznamů na stránku, změně vyhledávacího textu či archívu dojde k novému requestu na server, jehož obsah může vypadat podobně, jako je znázorněno níže. Ten je samozřejmě nutné zpracovat a vrátit požadovaná data zpět.
V systému pro SunOutdoor jsem si řešení vytvořil sám, což byla klasická začátečnická chyba. Protože již existují hotové knihovny přímo do Laravelu, jako třeba Laravel-Datatables. Ty stačí navázat na model nebo kolekci a o zpracování requestu a správný formát response se již postará.
[
"draw" => "1",
"columns" => [
0 => [
"data" => "name",
"name" => null,
"searchable" => "true",
"orderable" => "true",
"search" => [
"value" => null,
"regex" => "false",
]
],
1 => [
"data" => "term_range",
"name" => null,
"searchable" => "true",
"orderable" => "false",
"search" => [
"value" => null,
"regex" => "false",
]
],
2 => [
"data" => "payment",
"name" => null,
"searchable" => "true",
"orderable" => "false",
"search" => [
"value" => null,
"regex" => "false",
]
],
3 => [
"data" => "price_to_pay",
"name" => null,
"searchable" => "true",
"orderable" => "false",
"search" => [
"value" => null,
"regex" => "false",
]
]
],
"order" => [
0 => [
"column" => "1",
"dir" => "asc",
],
1 => [
"column" => "3",
"dir" => "asc",
]
],
"start" => "0",
"length" => "30",
"search" => [
"value" => "Pavel",
"regex" => "false",
],
"archive" => "2020",
]
Osobní zkušenosti s DataTables či jinou alternativou můžete sdílet v komentářích
K tomuto článku již není možné přidávat další komentáře