Rendering CSS with Data Attributes
To show how versatile our
SortController is, we’ll use it to fix a different problem with our schedule page. Right now, if we edit a concert on the page and change its start time, the concert page does not resort to insert the concert based on its new time.
This is admittedly a small problem, even by the standards of this sample app, but it has a neat solution, and it shows a technique based on Hey.com for leveraging Turbo and Stimulus that you may not have thought of.
Currently, the concerts are displayed in a nested loop. We have a list of days, we loop over each day, and then we loop the concerts on that day to display the page. We’ll replace that behavior with a simple list of concerts sorted by start time. Our sort controller can then handle the concert list. The problem with displaying the concerts in a single list, however, is that we lose our headers at the beginning of each day. We’re going to get them back by using plain old CSS.
First, we need to solve one problem. As written, each concert is wrapped in a Turbo Frame. When the Edit button is pressed, Turbo Frames changes the inner HTML of the frame to display the form and then, when the form is submitted, it changes the inner HTML again to display the edited concert.
Our problem is how updating the inner HTML of the form submission will affect our sort. As with the favorites example, our sort controller will be sorted based on the outermost part of each concert’s HTML display, which is the
turbo-frame tag. We’ll need to put the start date as a sort value on that tag, just like we did for the favorites. The new favorites were being created with Turbo Streams as brand-new DOM elements all the way through. though. The form submissions are using Turbo Frames and are only changing the text inside the
turbo-frame, however, meaning that if we change the date of the concert in the form, any change to the sort value attribute on the outer
turbo-frame itself won’t be picked up and the concert won’t be re-sorted.
A solution is to make the form response a Turbo Stream with a
replace action rather than a Turbo Frame response. By doing so, the entire
turbo-frame tag is replaced, including the outer frame itself, which means that any sort of value attributes we place on the
turbo-frame will also change.
To do this, we need to add one line of code to the controller method to specify a response for
turbo_stream formats, much the way we did for the
FavoritesController back in Turbolinks: