omines / datatables-bundle

DataTables bundle for Symfony
https://omines.github.io/datatables-bundle/
MIT License
251 stars 113 forks source link

Add Names to DataTable ColumnDefs / Columns [Column Filtering] #314

Open arlenreyb opened 8 months ago

arlenreyb commented 8 months ago

I guess this isn't really an issue, but I don't know enough about git to make this a pull request or whatever, and I wanted to share this in case others were looking for something like this:

Thanks to this bundle, you can apply a server-side table search from javascript very easily: datatable.column(0).search('2023-10-12').draw();

When this Ajax call from the datatable goes back to the controller, it's already POSTing columns. In Symfony's debug profiler, you can even see the POSTed columns array contains a field for name, though it's empty. But the name you gave it in PHP is there, under the 'data' key instead. You can also see the "search" key for that column, with the search setting applied to that column, and only that column. It's up to us to intercept that in the PHP controller and apply it to the datatable, and I won't get in to that (unless you want me to), but so far this is pretty nice ...

... except for the fact that you need to somehow communicate which column is which, by index number, between PHP and JS. That's not so great.

But check this out: https://datatables.net/reference/option/columns.name

Naming columns during datatable init allows you to access columns by name in JS. Since names defined in the PHP file are already passed to this bundle's JS config, it should be easy to add those same names to the column config.

If you do this, not only can you now do the following in JS (assuming column 0 was named 'createdAt' in the PHP controller): datatable.column('createdAt:name').search('2023-10-12').draw();

But now you can also see that the POST parameters from the ajax call now have the "name" key filled in. Which means you can easily get to search values in your PHP controller with:

$columnData = $request->request->all('columns');
$createdAtIndex = array_search('createdAt', array_column($columnData, 'name'));
$createdAtSearchValue = $columnData[$createdAtIndex]['search']['value'];

(Granted, before you could have array_searched by the 'data' column, but actually using the previously-empty name field feels better.)

I accomplished this by adding a single line of code at line 100 in datatables.js (the included supplementary js file for this bundle): dtOpts.columns.forEach(column => column.name = column.data);

Maybe you have a more elegant solution, or would rather put it somewhere else, but I figured I'd share this because (at least in my use case) it massively increased the usability of this bundle. I figured it might be useful for others, too.

github-actions[bot] commented 6 months ago

Stale issue message

github-actions[bot] commented 3 months ago

Stale issue message

arlenreyb commented 2 months ago

Hi. Bumping this because I found that "more elegant solution" I was looking for.

Again, here's DataTable's amazing "by name" API system: https://datatables.net/reference/option/columns.name In order to utilize this, you need to name the columns at init, which I was accomplishing by modifying that omines datatable.js file. This wasn't ideal, since every time packages updated or I pulled my project to a different workstation, those changes would be reset.

But then I stumbled upon this: https://datatables.net/examples/advanced_init/html5-data-options.html You can very easily add the name to the init through html 5 data attributes.

So, all you need to do now is grab a copy of the Omines twig template, drop it in your project template folder, and make this one, very simple change:

{% for column in datatable.columns %}
  <th data-name="{{ column.name }}">{{ column.label|trans }}</th>
{% endfor %}

More info on that, here: https://omines.github.io/datatables-bundle/#configuration Update your datatables.yaml file to point to the new template: template: 'datatable/datatable_modified.html.twig' (or whatever you called it)

So now all you have to do in your stimulus controller is eventually say:

datatable.column('columnName:name').search('searchValue').draw();

Then get that searchValue from the request in your controller, which is now named correctly so it's 100x easier to take that and apply it directly to the Omines adapter and apply specific column filters, or other advanced query shenanigans. I like this, because it lets me filter by a specific column (or multiple columns), and then do the global search on top of it.

Anyway, just wanted to share, in case anyone else was looking for DataTable's name API integration.

curry684 commented 2 months ago

Interesting approach, thanks for sharing 👍

Shotman commented 1 month ago

Hi. Bumping this because I found that "more elegant solution" I was looking for.

Again, here's DataTable's amazing "by name" API system: https://datatables.net/reference/option/columns.name In order to utilize this, you need to name the columns at init, which I was accomplishing by modifying that omines datatable.js file. This wasn't ideal, since every time packages updated or I pulled my project to a different workstation, those changes would be reset.

But then I stumbled upon this: https://datatables.net/examples/advanced_init/html5-data-options.html You can very easily add the name to the init through html 5 data attributes.

So, all you need to do now is grab a copy of the Omines twig template, drop it in your project template folder, and make this one, very simple change:

{% for column in datatable.columns %}
  <th data-name="{{ column.name }}">{{ column.label|trans }}</th>
{% endfor %}

More info on that, here: https://omines.github.io/datatables-bundle/#configuration Update your datatables.yaml file to point to the new template: template: 'datatable/datatable_modified.html.twig' (or whatever you called it)

So now all you have to do in your stimulus controller is eventually say:

datatable.column('columnName:name').search('searchValue').draw();

Then get that searchValue from the request in your controller, which is now named correctly so it's 100x easier to take that and apply it directly to the Omines adapter and apply specific column filters, or other advanced query shenanigans. I like this, because it lets me filter by a specific column (or multiple columns), and then do the global search on top of it.

Anyway, just wanted to share, in case anyone else was looking for DataTable's name API integration.

Do you have any example for a minimal repository on how it might work ?