【问题标题】:Turbo stream partial rendering as plain text in Rails 7在 Rails 7 中将 Turbo 流部分渲染为纯文本
【发布时间】:2022-10-02 11:10:46
【问题描述】:

我正在构建一个新的 Rails 7 应用程序,并尝试遵循 turbo 流的预期默认用途来替换 ajax 内容(以及需要其他 JS 控制的刺激)。这是我第一次使用 Turbo Drive。

我也在使用视图组件 (https://viewcomponent.org/)。

问题是来自服务器的响应似乎被浏览器视为纯文本。我在 Chrome 和 Brave 中尝试过,响应 mime-type 符合预期(text/vnd.turbo-stream.html 每个浏览器报告的响应标头)。此外,浏览器控制台报告 window.Turbo 已定义,因此 Turbo 似乎在客户端 JS 上可用。

作为起点,这是在预期操作之前的初始显示期间呈现的 html 的 sn-p:

<div class=\'grid grid-cols-2 gap-4\'>
  <div class=\'card bg-base-100 shadow-x1 mb-4\'>
    <div class=\'card-body\'>...some text here...</div>
    <div class=\'card-actions justify-center\'>
      <form class=\"form-control w-full max-w-xs pb-2\" action=\"/someroute.turbo_stream\" accept-charset=\"UTF-8\" method=\"get\">
        <div class=\'input-group\'>
          <input placeholder=\"Bring out your text\" class=\"input input-secondary w-full\" type=\"text\" name=\"location_text\" id=\"location_text\" />
          <input type=\"submit\" name=\"commit\" value=\"Button Legend\" class=\"btn btn-secondary w-fit px-2\" data-disable-with=\"Button Legend\" />
        </div>
      </form>
    </div>
  </div>
</div>
.
.
.
<turbo-frame data-turbo=\'true\' id=\'some-container\'>
  <div class=\'border rounded p-4 mb-4\'>
    <div class=\'text-center mb-2\'>...some text...</div>
  </div>
</turbo-frame>

目的是在提交按钮表单时替换some-container html(参见上面的&lt;input type=\"submit\"...&gt;)。请注意,我打算将其作为 GET 操作(请参阅 <form ...> 元素)。

那部分工作正常。按下按钮,我的控制器按预期触发。

控制器:

def show
  # ...other code to prepare content...
  respond_to do |format|
    format.turbo_stream
    format.html do
      raise \'unexpectedly HTML format\'
    end
  end
end

show.turbo_stream.haml:

= turbo_stream.replace \'#some-container\' do
  = render SomeContainerComponent.new(<some arguments>) # just for interior content

为了以防万一,这里是组件的 HAML(相同的组件用于最初呈现页面,目的只是更新它):

%turbo-frame#some-container{data: {turbo: \'true\'}}
  .border.rounded.p-4.mb-4
    = render(AnotherComponent.new(<some arguments>))

从我所见,我真的需要涡轮框架元素,因为 some-container 的 id 应该足够了。而且我也不应该需要data-turbo=true(据我所知,我还没有禁用Turbo。)。我已经尝试过使用和不使用这些部件,但没有任何明显的变化。

唯一似乎相关的另一件事是分享这是页面视图布局中涉及 JS 的行:

= javascript_include_tag \'application\', \'data-turbo-track\': \'reload\', defer: true

尽管如此,当我提交表单时,来自服务器的响应将页面替换为 HTML 的纯文本呈现,旨在用于替换 #some-container 元素,并且看起来格式正确。

这是 HTML 响应在浏览器上的样子:

<turbo-stream action=\"replace\" target=\"#some-container\"><template><turbo-frame data-turbo=\'true\' id=\'some-container\'>
.
.
.
...HTML elements for the content to be displayed...
.
.
.
</turbo-frame>

</template></turbo-stream>

由于表单提交并触发了控制器,看来这实际上只是一个与 Turbo 的 JS 相关的问题。我总是可以使用remote: true 回退到较旧的UJS 表单并明确处理ajax:success,但我想在Rails 7 中使用Turbo 制作显然是新推荐的方法。

有什么建议如何让它停止以纯文本形式呈现响应 sn-p 吗?

    标签: ruby-on-rails hotwire-rails turbo


    【解决方案1】:

    不要向 url 添加格式扩展名。无论如何,Turbo 仅适用于html。如果扩展名是x?html 或为空,涡轮踢in。如果是其他内容,则常规请求是sent。请注意,提交表单时,页面实际上会完全刷新。对/page.turbo_stream 的请求会呈现带有<涡轮流>标签(无布局,无 javascript)和标题 Content-Type: text/vnd.turbo-stream.html;。因为它不是文本/html,浏览器将其呈现为纯文本。

    首先,只需使用<涡轮框架>.

    <%= form_with url: "/path",
        method: :get,
        data: { turbo_frame: :form_response } do |f| %>
      <%= f.submit %>
    <% end %>
    
    <%= turbo_frame_tag :form_response %>
    

    响应为 html 格式:

    format.html { render :something }
    

    它看起来像这样:

    <!-- Anything else on this page outside of this frame will be discarded -->
    <%= turbo_frame_tag :form_response do %>
      <dialog open>
        <p>Updated</p>
        <form method="dialog"><button type="submit">Close</button></form>
      </dialog>
    <% end %>
    

    得到流仅在最近的测试版中受支持 v7.2.0-beta.1https://github.com/hotwired/turbo/pull/612

    # Gemfile
    
    # gem "turbo-rails"
    gem "turbo-rails", github: "hotwired/turbo-rails", branch: "turbo-7-2-0"
    

    更新

    得到流已登陆turbo https://github.com/hotwired/turbo/releases/tag/v7.2.0

    将turbo-rails 更新为v1.3.0

    【讨论】:

    • 谢谢你的明确回答,尤其是。建议重新测试版!看起来我根本不需要 Streams,只需要 Frames。我今天就试试这个!
    • 有效!谢谢!一旦你指出我正确的方向,肯定会变得直截了当。一个注释,我确定这个 ViewComponents 问题但共享所以它是已知的:我必须将include Turbo::FramesHelper 添加到我的组件中(现在我可以将其推广到所有 Turbo 助手的所有组件)以使 turbo_frame_tag 可用。显然,基础 gem(或其 ViewComponent::Base)并没有从 ActionView 上下文中引入它。刚投进去
    猜你喜欢
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    相关资源
    最近更新 更多