Comments (5)
@dhh I am thinking that this is going to be a pretty common use case. Consider the common demo example of a simple chat application where you would likely want a message to appear different for the messenger or for people who are mentioned in a message. I can imagine there are many ways to solve this problem but I am curious if you have a few more details about the solution you are proposing to this problem involving Stimulus controllers.
from turbo-rails.
The way I achieved this was by making Turbo broadcast twice, once with the partial for guests, with no rendered controls to be able to "like" or "comment", and once for logged in users, with rendered controls.
It's not perfect, and it may or may not be desirable because it effectively doubles the amount of server work when doing an update, but depending on your app it's slightly more sanitary than having controls you don't want users having just being hidden in the DOM - even if your server handles it correctly when a guest tries something they shouldn't.
class Listing < ApplicationRecord
after_create_commit do
broadcast_append_to "private_listings", target: "private_listings", partial: "listings/listing", locals: { listing: self }
broadcast_append_to "public_listings", target: "public_listings", partial: "listings/public_listing", locals: { listing: self }
end
after_update_commit do
broadcast_replace_to "private_listings", partial: "listings/listing", locals: { listing: self }
broadcast_replace_to "public_listings", target: "public_listings", partial: "listings/public_listing", locals: { listing: self }
end
after_destroy_commit do
broadcast_remove_to "private_listings"
broadcast_remove_to "public_listings"
end
end
<% channel_name = current_user.present? ? 'private_listings' : 'public_listings' %>
<%= turbo_stream_from channel_name %>
<%= turbo_frame_tag channel_name, class: 'row' do %>
<%= render @listings %>
<% end %>
from turbo-rails.
You can also show one version to the person who created a Listing
, with controls to edit and delete their own records, and one to the general public.
The after_initialize
is used because the after_destroy_commit
throws a Frozen error when broadcast tries to traverse the users
association, so we can cache the GlobalID
on init.
class Listing < ApplicationRecord
attr_accessor :user_gid
belongs_to :user, inverse_of: :listings
after_initialize do
self.user_gid = user.to_gid_param
end
after_create_commit do
broadcast_append_to [user_gid, "private_listings"], target: "private_listings", partial: "listings/listing", locals: { listing: self }
broadcast_append_to "public_listings", target: "public_listings", partial: "listings/public_listing", locals: { listing: self }
end
after_update_commit do
broadcast_replace_to [user_gid, "private_listings"], partial: "listings/listing", locals: { listing: self }
broadcast_replace_to "public_listings", target: "public_listings", partial: "listings/public_listing", locals: { listing: self }
end
after_destroy_commit do
broadcast_remove_to [user_gid, "private_listings"]
broadcast_remove_to "public_listings"
end
end
<%= turbo_stream_from [current_user, 'private_listings'] %>
<%= turbo_frame_tag 'private_listings', class: 'row' do %>
<%= render @listings %>
<% end %>
from turbo-rails.
You'll need to make a partial that's not dependent on global state like this to work. You can use client-side show/hide using a stimulus controller instead. Would be happy to see some documentation covering this. PDI!
from turbo-rails.
So one way I have found to do this is to inject css styling per user that would adjust the visibility of elements within a partial using the dom_id as a class.
import { Controller } from "stimulus"
export default class extends Controller {
static values = { participantId: String }
connect() {
var style = document.createElement('style');
style.innerHTML = `
#${this.element.id} .model_${this.participantIdValue}.default {
display: none;
}
#${this.element.id} .model_${this.participantIdValue}.hidden {
display: block;
}
`;
document.head.appendChild(style);
}
}
One drawback to this approach is that you need to add two versions of each partial to every user's html which seems a bit ugly. I am also guessing that there may be complications as a UI gets more involved.
I am curious if anyone else has come up with other cleaner solutions.
from turbo-rails.
Related Issues (20)
- `refresh` action is missing from Turbo::Streams::TagBuilder HOT 5
- Turbo Frame Responses missing tracked elements HOT 6
- Usage of anchor HOT 5
- Websocket doesn't work on production
- rails tests fail after turbo-rails upgrade from 1.5.0 to 2.0.3 HOT 4
- Single quotes not properly handled in Turbo Streams broadcast
- Content duplication on using render in controllers HOT 1
- Chrome reloads assets in the Link preload header HOT 1
- Uglifier::Error during assets:precompile HOT 1
- Turbo not streaming changes properly / window.Turbo is undefined HOT 3
- InstaClick prefetch not working with fragment cache
- Prefetch causes turbo stream to render on hover instead of on click HOT 2
- Inverted parameters in stream responses HOT 2
- unexpected routes added as part of the turbo rails gem HOT 2
- When streaming from a worker, path helpers append a domain `https://example.com` HOT 5
- Turbo Documentation need a "Broadcast" chatper
- Refresh broadcasts generated without changes
- Incompatible with Solid_Queue HOT 1
- turbo_frame_request_id safe operator in not handled correctly HOT 2
- Shouldn't broadcast refresh if streamables == [nil] HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from turbo-rails.