2

I'm trying to add live update functionality to a statistics page using Turbo. The page has a user-set date range with a simple filter using url params. The value of each stat is determined by summing values of a collection of objects (matched by the date range).

Everytime an object updates in the db, the stats need to refresh if they relate to this object (i.e. the object has a date_created within the date range that the user has selected on the filter).

In the controller

@things = Thing.where(:created_at => params[start_date]..params[end_date])

In the view

<%= turbo_stream_from "profit" %>
<%= render 'profit_card', things:@things %>

The rendered partial (profit_card)

Total Profit: <%= things.sum(&:profit) %>

What I would like to add to the Thing model is

after_update_commit { broadcast_replace_to "profit", partial: "profit_card", locals: {things: ???} }

The problem is that there is no way of putting the right collection @things into the above line. The specific @things are filtered in the controller depending on the date range selected.

If the filter only selected a single date (and not a range), this could be done like this:

broadcast_replace_to "profit_#{thing.created_at}", partial: "profit_card", locals: {Thing.where(created_at: self.created_at)}

And then in the view

<%= turbo_stream_from "profit_#{selected_date_from_params}" %>

This however doesn't work with date ranges, as there are too many combinations.

Is there another way to achieve this functionality using turbo?

Thanks very much!

daveanderson88
  • 327
  • 1
  • 4
  • 12
  • It is rather tricky to combine server-side rendering from Turbo with client-side input, when the input params does not trigger Turbo. I think Streams alone do not provide a solution there, however Hotwire as a whole does have solutions to this dilema. In general when you want to achieve a combination of client-side and server-side interactivity in Hotwire, you need to use stimulus. MutationObserver is a way to observe if any streams are incoming, which can help you triggering an action (for example, re-filtering the data you have on the view) – kkp Feb 23 '23 at 11:19
  • Thanks. In the end I used Stimulus to immediately set the dom element to hidden if it did not meet the conditions of the filter params within the connect() method. – daveanderson88 Mar 02 '23 at 06:58

0 Answers0