Turbo 响应呈现 javascript 警报?

Turbo response to render javascript alert?

提问人:nimmolo 提问时间:11/4/2023 最后编辑:nimmolo 更新时间:11/23/2023 访问量:118

问:

我正在重构 和 的 Rails 控制器,并试图了解如何在 Turbo 中执行应用程序当前使用 JS 响应模板执行的操作。turbostimulus

在一个页面上,我有一个按钮可以请求文本记录的“先前版本”。things#showthing

目前,在 Rails UJS 中,此按钮向操作发送 GET JS 请求。该操作通过为 (包含版本的文本,从 db 中提取)设置一个 ivar 来响应,并呈现一个单行 js 模板:things/versions_controller#show@versions

# things/versions/show.js.erb

alert('<%= @versions %>');

我明白了,使用 Turbo,模板必须简单地呈现turbo_stream标签并更新/附加/替换页面元素。警报超出了该范围。

有没有办法将 ruby ivar 直接传递给 Stimulus 控制器,从而显示 js 警报?我能想象到的唯一方法是,Stimulus 控制器将处理点击,向操作发出获取请求(这将给出 HTML 响应),并处理响应本身。没有涡轮增压器。@versionsthings/versions_controller#show

我想我可以让涡轮响应打印一个隐藏的包含页面中的,并将该帧附加到激励控制器,一旦帧连接到 DOM,该控制器就会将文本抛出警报。但这似乎过于做作了。turbo_frame@versions

我真的主要是想理解范式,找到最惯用的方式来做这样的事情,如果有的话。此外,我意识到警报很粗糙,我可以使用模态渲染来做到这一点。

JavaScript Ruby-on-Rails 刺激JS Turbo-Rails

评论


答:

3赞 trh 11/4/2023 #1

如果您要提交表单,则可以创建或更新涡轮响应,该响应会呈现许多内容,而不仅仅是一个内容。

例如,可以包含:create.turbo_stream.erb

<%- # with a partial %>
<%= turbo_stream.replace("flash-container", partial: "/layouts/notices") %>
<%- # with embedded html %>
<%= turbo_stream.update("turbo-modal", "<turbo-frame id='turbo-modal'></turbo-frame>".html_safe) %>

<%- # with local variables %>
<%= turbo_stream.update("some-turbo-tag", partial: "path-to-partial", locals: { version: @version }) %>

<%- # remove page sections not needed %>
<%= turbo_stream.remove("some-turbo-tag"}) %>

如果它不是形式,而是一个链接,那么要获得完整的涡轮流响应,而不是html,只需将或'data: { turbo_stream: ''}添加到您的link_to中,例如data-turbo-stream

<%= link_to "click me, its fun", show_something_path, data: { turbo_stream: true } %>

使用流渲染的好处是可以控制多个页面涡轮帧。需要注意的是,这样做存在一个长期存在的错误,因此请确保您使用的是 7.3 或更高版本。@hotwired/turbo-rails

2赞 Ben Trewern 11/4/2023 #2

我认为您可以像这样返回javascript:

<turbo-stream action="append" target="some_target">
  <template>
    <script>
      alert('<%= @versions %>');
    </script>
  </template>
</turbo-stream>
1赞 Alex 11/7/2023 #3

除了其他答案之外,您还可以进行自定义 Turbo Stream 操作,以使警报操作美观且可重用:

// app/javascript/application.js

Turbo.StreamActions.alert = function () {
  alert(this.templateContent.textContent)
};
# config/initializers/turbo_stream_actions.rb

# this is optional but makes it much cleaner
module CustomTurboStreamActions
  def alert text
    action(:alert, "#", text)
  end

  ::Turbo::Streams::TagBuilder.include(self)
end

在控制器中使用它作为对TURBO_STREAM请求的响应:

respond_to do |format|
  format.turbo_stream do
    # without CustomTurboStreamActions module
    # render turbo_stream: turbo_stream.action(:alert, "#", @versions)

    # with CustomTurboStreamActions
    render turbo_stream: turbo_stream.alert(@versions)
  end
end

https://turbo.hotwired.dev/handbook/streams#custom-actions

评论

0赞 nimmolo 11/8/2023
这很优雅!我在文档中缺少这样的东西。这是基本的,但试图想象 Turbo 如何做到这一点,我一直在想“不可能”。也许我会建议 Hotwire 添加一个带有此类示例的“迁移常见问题解答”。
0赞 nimmolo 11/22/2023
希望我能多投票支持。非常有用,例如在turbo_stream响应更新页面后隐藏模态。
1赞 Alex 11/22/2023
@nimmolo你可能想研究一下这些,如果不使用它们,至少看看事情是如何完成的:github.com/marcoroth/turbo_power github.com/stimulusreflex/stimulus_reflex github.com/stimulusreflex/cable_ready。我不使用其中任何一个,对于我的大多数需求来说,这有点太多了,但我实现了这些家伙为自己做的一些事情,看到源代码非常有帮助。
1赞 Alex 11/22/2023
例如,我完全从stimulus_reflex stackoverflow.com/a/76112894/207090 中窃取了“变形”动作
0赞 nimmolo 11/22/2023
哇。那东西很疯狂,非常有用。希望我用这个 20 岁的应用程序走得那么远!