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