Skip to content

Add the refresh_action #180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

alexandre-castelain
Copy link
Contributor

Add a new action, the RefreshAction, which, as the name suggests, provides a way to refresh the DataTable's content.

This is particularly useful when the data is updated from an external source, and the DataTable serves only as a display.

Copy link
Owner

@Kreyu Kreyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! I am not convinced yet of the use case, especially since it seems that adding a button action with current url would do the same thing, but I've added some questions in the review.

@alexandre-castelain
Copy link
Contributor Author

From my point of view, it's not exactly the same.

Firstly, it allows the DataTable to be reused in multiple contexts (potentially across several pages) without needing to know the URL to which it should be redirected. It simply redirects to the current URL, directly taking advantage of Turbo to update its content.

Secondly, redirecting to the page refreshes the entire page. Imagine a page containing four DataTables; all the data would have to be rebuilt again. Currently, given how Turbo works, that’s also the case (unless I’m mistaken). But we could change this behavior.

-> When refreshing a specific DataTable via a query parameter, we could indicate which DT should be refreshed.
-> In that case, within the handleRequest, if it isn’t the correct DT to refresh, don’t fetch the data—and therefore, avoid having to format it. Instead, return an “empty” DT. The complete page view would then contain the refreshed DT with its information and the three others empty. With Turbo refreshing only the frame corresponding to our refreshed DT, we would achieve the expected behavior.
-> Moreover, adding this option to refresh or not via handleRequest could also be used to make DataTables asynchronous. In other words, some tables containing large amounts of data (or simply taking a long time to load) might slow down the display of the entire page. We could add an option that initially doesn’t display any data in the DT, and then, once on the front end, refresh the frame and load ONLY that one DT.

I might be overthinking it, but I sincerely believe this would be an interesting feature to add to the bundle.

What do you think?

@FluffyDiscord
Copy link

If the refresh action isn't merged, at least merge the data_table_name Twig extension function. If we want to return data table in a stream to replace current one, we need to do this currently, which is prone to break if this package changes the name in any way:

// prone to break on any name change
return new TurboStreamResponse()->replace("#kreyu_data_table_".$dataTableView->vars["name"], $renderedDataTable);

// this would be immune to that
return new TurboStreamResponse()->replace("#".$extension->getDataTableName($dataTableView), $renderedDataTable);

@Kreyu
Copy link
Owner

Kreyu commented Feb 28, 2025

If the refresh action isn't merged, at least merge the data_table_name Twig extension function. If we want to return data table in a stream to replace current one, we need to do this currently, which is prone to break if this package changes the name in any way:

Data table name is not identifier of the turbo frame. It just so happens that name is a part of frame identifier in base theme. So, you would still have to do it like this:

return new TurboStreamResponse()->replace("#kreyu_data_table_".$extension->getDataTableName($dataTableView), $renderedDataTable);

I guess what you guys need is:

  • turbo_frame_id variable in data table view, instead of relying on "kreyu_data_table_" prefix that can change in the future
  • data_table_turbo_frame_id Twig function like @alexandre-castelain suggested, if you don't want to access the view vars directly

This could be expanded in the future allowing to define turbo frame identifier in data table options, or something like that, without breaking changes. Sure thing!

I'm up for data_table_name Twig function as well, but it needs to return name from the data table view.

@Kreyu
Copy link
Owner

Kreyu commented Feb 28, 2025

@alexandre-castelain Thanks for the explanation, I think I understand it better now.

We can start by adding the data_table_turbo_frame_id Twig function, that will return the kreyu_data_table_{{ name }}, so we can expand it in the future without introducing breaking changes.

Secondly, redirecting to the page refreshes the entire page. Imagine a page containing four DataTables; all the data would have to be rebuilt again. Currently, given how Turbo works, that’s also the case (unless I’m mistaken). But we could change this behavior.

So, we want to be able to tell which data table to render as turbo stream in the controller, right? If we rely on some parameter in the request, it should be added to pagination controls, filtration form, URLs to sort, am I right? That's what I deduced based on your explanation in ActionRefreshUrlGenerator, but it shouldn't be available exclusively in refresh action.

I wonder if adding a live component that renders the data table wouldn't be good use case to render tables individually, instead of relying on turbo streams. Damn I'm soooo inexperienced with Turbo and live components it may be a total miss 😅

@FluffyDiscord
Copy link

FluffyDiscord commented Feb 28, 2025

I think Turbo streams are the way to go. We have Form and Link actions which may go to any other part of our app, any endpoint. It's nicely decoupled and pluggable, and these endpoints may return the same data table with fresh data. Don't think that's possible with live components, because only they themselves are updated (as fsr as I understand them), unless we use some kind of event system or "action processors", that we could listen to and do something, which feels weird to me.

And no, Turbo won't refresh whole page, if you return response with only your table thats set to replace that one specific table.

@Kreyu
Copy link
Owner

Kreyu commented Feb 28, 2025

And no, Turbo won't refresh whole page, if you return response with only your table thats set to replace that one specific table.

@FluffyDiscord if you define multiple data tables on one page, how do you know which data table to render via turbo stream? Do you rely on the turbo-frame header?

@alexandre-castelain
Copy link
Contributor Author

@Kreyu yes, I think so. It's what I understand looking at the turorial on SymfonyCast : https://symfonycasts.com/screencast/turbo/frames-find-frames#adding-the-turbo-frame-in-the-response

@Kreyu
Copy link
Owner

Kreyu commented Feb 28, 2025

Reading through UX Turbo docs, this is my first thought on how would I handle this: https://gist.github.com/Kreyu/efa69130b531c07d41d2931f4f68bb30

This would mean no unnecessary queries in turbo streams, e.g. fetching products when interacting with categories.

Are we on the same page?

@alexandre-castelain
Copy link
Contributor Author

In the idea, yes, I think it's a good idea, but I would prefer to use the Trait (or another one) to simplify the work in the controller, like something like this : https://gist.github.com/alexandre-castelain/de62a66a455334152f2371fab562a9a6

We don't need to have multiple handleRequest depending if it's a Turbo call or not, in the handleRequest, we could use $request->headers->get('Turbo-Frame') to know if we need to fetch the data or not.

@Kreyu
Copy link
Owner

Kreyu commented Feb 28, 2025

Created a discussion in #196 because most of that is out of scope of this pull request and it was easier to summarize a little bit 😄

# Conflicts:
#	docs/src/docs/components/actions.md
#	src/Resources/translations/KreyuDataTable.ca.yaml
#	src/Resources/translations/KreyuDataTable.es.yaml
#	src/Resources/views/themes/base.html.twig
#	src/Resources/views/themes/bootstrap_5.html.twig
@alexandre-castelain
Copy link
Contributor Author

alexandre-castelain commented Mar 3, 2025

Hi @Kreyu !
I changed the code :

  • I added a configurable turbo frame identifier via option
  • I removed the ActionRefreshUrlGenerator, as it was kind of useless.
  • I added a default translation for the button
    Btw, if you don't want this feature, no problem, you can close this MR !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants