marcoroth / turbo_power-rails Goto Github PK
View Code? Open in Web Editor NEWPower-pack for Turbo Streams
License: MIT License
Power-pack for Turbo Streams
License: MIT License
Currently the helper generates <turbo-stream>
elements always with the <template>
tag, we should just generate it when it's actually needed.
For example, this call:
turbo_stream.reset_form("#form")
Currently generates:
<turbo-stream action="reset_form" targets="#form"><template></template></turbo-stream>
Hey @marcoroth
I just tried to do a:
pin "turbo_power", to: "turbo_power.js"
as in the README (instructions I put in with my PR 😀 btw) and the browser console throws an error that turbo_power.js
cannot be found.
I looked in the Rails asset paths Rails.application.assets.paths.map { |path| puts system("ls #{path}/") }; nil
and yeah, there is no turbo_power.js
nor any paths provided from this gem.
I'm using the latest gem 'turbo_power'
, which at this time is 0.1.6
.
This for this gem, it's making my cable_ready migration possible without totally re-writing. Would you be interested in adding method chaining? Similar to cable_car
from cable_ready?
I worked this out:
class ApplicationController < ActionController::Base
def stream_car
StreamCar.new(method(:turbo_stream))
end
class StreamCar
def initialize(meth)
@meth = meth
@buffer = ActiveSupport::SafeBuffer.new
end
def to_s
@buffer.to_s
end
def to_str
@buffer.to_str
end
def method_missing(name, *args, **kwargs)
@buffer << @meth.call.send(name, *args, **kwargs).html_safe
self
end
end
end
Use by...
def update
render turbo_stream: stream_car.remove_css_class("#launch-card").set_value("#user_invite_form_name", value: "")
end
Surprisingly, it works. Happy to make a PR and battle-test it more; just wanted to ask.
Hey @marcoroth
Really love the work you're doing with this project so far. Managed to use it for some of the modals at aitoolsfor
However, i think adoption of this project could improve if we added some examples for people to reference. Happy to work with you on this one if you could provide some guidance! 🙏
Some googling didn't show any tutorials or guides so it's a little tricky sometimes.
Let me know what you think!
Hi, we're loving this gem. It's got a lot of really great abilities in here.
I spent a little while debugging an issue when I was using one of the actions today. I had a turbo stream template which was rendering several turbo stream actions
= turbo_stream.append dom_id(@model, "list"), ...
= turbo_stream.replace dom_id(@model, "map_pin"), ...
-# other turbo streams here
And we wanted to add a new stream for changing an attribute. Turbo power has the set_attribute
action for this!
= turbo_stream.set_attribute dom_id(@model, "map"), ...
This failed however, and you might be able to guess why. Almost all of the Turbo Power actions use the custom_action_all
helper, which sends builds turbo stream tags using the targets
attribute. When you use the targets
attribute then the Turbo JS switches to using querySelectorAll
instead of findElementByID
to locate your target. That took us a bit of time but we eventually figured out we needed to prefix our dom_id
with a #
in order to get everything working.
= turbo_stream.set_attribute "##{dom_id(@model, "map")}", ...
This is a little bit uglier, but it's workable.
Turbo has started to establish a convention with the stream helpers where calling an action sets the target
attribute, and the *_all
helpers sets the targets
attributes (e.g. append
vs append_all
).
I think we could add the same thing in Turbo Power where it makes sense. That would involve making many additional helpers and having set_attribute_all
in addition to set_attribute
. I saw your rejected PR which would have made this quite a bit easier as we could have passed target
/targets
ourselves, as needed. In lieu of that, however, adding all
versions of these actions might be good for consistency. Would you accept a PR which added these or do you have any other ideas of how to achieve this consistency a little better? The biggest downside I can see besides doubling the API surface is it would be a breaking change for the existing API. Let me know what your thoughts are, please!
It shouldn't matter if you are using @hotwired/turbo
or @hotwired/turbo-rails
, TurboPower should work either way.
As pointed out in #2 and #3 (comment) it seems like there are some inconsistencies. The following snippets should work:
import * as Turbo from "@hotwired/turbo"
import TurboPower from "turbo_power"
TurboPower.initialize(Turbo.StreamActions)
import { StreamActions } from "@hotwired/turbo"
import TurboPower from "turbo_power"
TurboPower.initialize(StreamActions)
import { Turbo } from "@hotwired/turbo-rails"
import TurboPower from "turbo_power"
TurboPower.initialize(Turbo.StreamActions)
Does it work correctly with Turbo 8 ?
Can it be used with Turbo 8? what problems?
ArgumentError (You invoked render but did not give any of :partial, :template, :inline, :file, :plain, :html or :body option.):
, while the same usage with set_attribute
does not.
turbo_stream.set_value('#order_form_manual_time', '')
=> throws exception
turbo_stream.set_attribute('#order_form_manual_time', 'value', '')
=> works
I looked briefly at https://github.com/marcoroth/turbo_power-rails/blob/main/lib/turbo_power/stream_helper.rb
and everything seems in order.
I can do more investigating and attempt to produce a failing test later but wanted to get this potential issue recorded.
Pull Request #12 removed the ability to use the block rendering and partial rendering syntax for Turbo Streams actions.
We should restore this functionality:
<%= turbo_stream.inner_html "body" do %>
New Body
<% end %>
and
<%= turbo_stream.inner_html "#post_1", partial: "posts/post", locals: { post: @post } %>
The turbo-rails gem pins thus to the config/importmap.rb
file:
pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true
When I ran bin/importmap pin turbo_power
it did pin a version of @hotwired/turbo
but since I didn't want two versions of Turbo, I removed it and received this error:
Uncaught TypeError: Failed to resolve module specifier "@hotwired/turbo". Relative references must start with either "/", "./", or "../".
As a workaround, I just made a "copy" in config/importmap.rb
like so:
pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true
+pin @hotwired/turbo', to: 'turbo.min.js', preload: true
After that no problems and I've already implemented a .set_attribute()
stream. 🚀
Thanks for this great gem and NPM package.
I tripped across this today, but not sure if this is by design / unavoidable in turbo, or a bug?
I have a turbo frame with a src like:
<turbo-frame id="blah" src="/blah/1">
in my rails controller, on another action (let's say I'm editing blah) I tell it to reload that frame:
#blah_controller
def edit
#do stuff
render turbo_stream: turbo_stream.turbo_frame_reload('blah')
end
Then the turbo frame src of the frame I'm reloading changes to:
<turbo-rame id="blah" src="/blah/1/edit">
which is incorrect, the src should stay the same.
Is this intentional, or due to some side effect of Turbo reloading? IMO, the src of a turbo frame should never change. And its causing unexpected issues in my app because of the url its putting there.
Thanks for this really helpful gem
currently my view looks anything like that:
= turbo_stream_flash
- if status_success
= turbo_stream.redirect_to( admin_responsibilities_path, "advance")
- else
= turbo_stream.replace 'responsibility-form' do
= render 'form'
Would it be possible to make theese helpers available or some of that available in controller?
Or, at least some of them, like the redirect_to
this should, on rendering, adding the tag to the view, so, that turbo can handle the redirect.
this would simplyfiy CRUD actions like that:
def create
@responsibility = Responsibility.new(responsibility_params)
if @responsibility.save
turbo_stream.redirect_to(admin_responsibilities_path, "advance")
else
render status: :unprocessable_entity
end
end
Bump gemspec to allow https://github.com/hotwired/turbo-rails/releases/tag/v1.4.0
Hi,
Many of your functions have the first attribute: targets
.
I made a test on turbo_frame_set_src
and noticed that its interpreting a simple string as id, because: #cars-box
does not work while cars-box
successfully targets the element with the id cars-box
.
So under targets
I would expect that a value like .cars-box
would affect all matching elements as it would be the case with jquery.
Could you please clarify this?
On my gem, which includes yours in many cases, I kept the same naming because I thought target
was a good naming for what it means, but clarified that target has a value like #my-target
in logs, for example.
And why not allow css matchers like .customer-wrapper > #form
? Yes, html-id should be unique, but this is hard to control and for complex pages child selectors would be a help.
Thanks,
Chris
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.