I'm upgrading an application from rails 6 to 7 and replacing ujs with turbostreams.
The current ujs
$('#sightings_by_type').html("<%= escape_javascript (render partial: '/member/spotting_sessions/sightings_by_stock_type', locals: { editable: true }) %>")
$('#sighting_added_confirmation').css('display', 'block')
$('#sighting_added_confirmation').fadeOut(2000)
I'd like to replace the fadeOut call, and changing display, with a css class I've got available. However I can't figure out how I should add the class by using the turbo_stream.haml file. It seems that the turbo_stream can act upon the entire contents of an element (replacing a div, etc) but not down to the low level of changing attributes of an element.
Is turbo_streams the wrong way to tackle this?
I could put the logic into the stimulus controller but that doesn't feel the appropriate place for that.
This is the add_sighting.turbo_stream.haml so far:
= turbo_stream.update "sighting_details", partial: "/member/spotting_sessions/sightings_by_stock_type", locals: { editable: true }
You can use javascript in your turbo streams:
<%= turbo_stream.update "sighting_details", partial: "/member/spotting_sessions/sightings_by_stock_type", locals: { editable: true } %>
<%= turbo_stream.after "sighting_details" do %>
<script charset="utf-8">
$('#sighting_added_confirmation').css('display', 'block')
$('#sighting_added_confirmation').fadeOut(2000)
</script>
<% end %>
You can make custom turbo stream actions:
// app/javascript/application.js
Turbo.StreamActions.style = function () {
this.targetElements.forEach((target) => {
target.style = this.templateContent.textContent
});
};
<%= turbo_stream.action :style, :sighting_details, "display: block;" %>
Optionally, you can make it a method:
# config/initializers/turbo_stream_actions.rb
module TurboStreamActions
def style(...)
action(:style, ...)
end
Turbo::Streams::TagBuilder.include(self)
end
<%= turbo_stream.style :sighting_details, "display: block;" %>