ruby-on-rails - rails 7 : Turbo stream is showing partial only

标签 ruby-on-rails

我的涡轮 rails gem 有问题。首先,我在 Rails 7 应用程序中安装了最新版本。在我的网站上,我有一个包含在表单中的选择输入,该表单下方的一部分显示了数据。现在我想使用 select 应用过滤器并使用此 Turbo-rails 包动态更新数据。我的表单 html 如下所示:

<div class="users">
    <div class="filters">
        <%= form_with url: '/users/load', method: :get, data: { turbo_frame: :form_response } do |form| %>
            <%= render partial: "shared/select", locals: {
                placeholder: 'Gender', 
                width: '90px', 
                options: @genders,
                classes: 'filter',
                name: 'gender',
            } %>
            <%= form.submit %>
        <% end %>
    </div>

    <%= turbo_frame_tag :form_response do %>
        <%= render partial: "users/user_list", locals: {
            users: @users
        } %>
    <% end %>
</div>

在我的路由中,我创建了这个 get 请求,该请求被转发到 Controller 中的 load 方法,如下所示:

get '/users' => "users#index"
get '/users/load' => "users#load"

然后在我的 Controller 中我有这样写的 2 个方法:

class UsersController < ApplicationController

    before_action :require_user

    USERS_PER_PAGE = 15

    def index
        @genders = ["Male", "Female"]
        @users = User
                            .limit(USERS_PER_PAGE)
                            .order(:creation_date).reverse_order
    end

    def load
        @users = User
                            .limit(USERS_PER_PAGE)
                            .order(:creation_date).reverse_order
                            
        if params[:gender]
            @users = @users.where(gender: params[:gender])
        end

        respond_to do |format|
            format.html { render partial: 'users/user_list', locals: { users: @users } }
        end
    end
end

问题是,当我进入此页面,选择性别并点击提交按钮时,我可以看到具有正确性别的用户数据,但我只看到部分加载,因此页面的其余部分是走了。我可以在 Chrome 开发者工具的网络选项卡中看到请求 header 设置为:

text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

我想使用涡轮流而不是涡轮帧,因为我需要在同一页面上更新更多这些项目。为什么它不渲染页面内的内容,而是仅渲染部分内容?

如何解决这个问题?

最佳答案

为了回答您的问题,您正在渲染没有 Turbo 流或 Turbo 帧的部分,因此您只能得到部分作为响应。

我认为,几个例子就能解释一切。

# config/routes.rb
resources :users
# app/controllers/users_controller.rb
def index
  scope = User.order(created_at: :desc)
  scope = scope.where(name: params[:search]) if params[:search]
  @users = scope
end

“保留日志”在使用 Turbo 框架时非常有用,它会重定向并清除控制台:
https://developer.chrome.com/docs/devtools/console/reference/#persist


Turbo FRAME 使用 GET 请求和 HTML 响应

我们正在进行 index 操作,表单正在提交回 index

# app/views/users/index.html.erb

# expect :users_index turbo frame in a response      vvvvvvvvvvvvvvvvvvvvvvvvv
<%= form_with url: users_path, method: :get, data: { turbo_frame: :users_index } do |f| %>
  <%= f.text_field :search %>
  <%= f.submit %>
<% end %>

# turbo frame in a response needs to match turbo frame on the current page,
# since we're rendering the same page again, we have the matching frame,
# only content inside this frame is updated.
<%= turbo_frame_tag :users_index do %>
  <%= render @users %>
<% end %>

# If you render some other page, you have to wrap it in
# `turbo_frame_tag :users_index`

如果您也想更新网址,这样刷新时就不会丢失搜索:

<%= turbo_frame_tag :users_index, data: { turbo_action: :advance } do %>
  <%= render @users %>
<% end %>

Turbo STREAM 使用 GET 请求和 TURBO_STREAM 响应

您必须设置data-turbo-stream="true"才能发送GET流。

# app/views/users/index.html.erb

<%= form_with url: users_path, method: :get, data: { turbo_stream: true } do |f| %>
  <%= f.text_field :search %>
  <%= f.submit %>
<% end %>

<%= tag.div id: :users_index do %>
  <%= render @users %>
<% end %>

添加 turbo_stream 格式来响应此请求:

# app/views/users/index.turbo_stream.erb

# update content inside <div id="users_index">
<%= turbo_stream.update :users_index do %>
  <%= render @users %>
<% end %>

# add another `turbo_stream` here if you'd like.

Turbo STREAM 使用 POST 请求和 TURBO_STREAM 响应

# config/routes.rb

resources :users do
  # # add `search` action
  # post :search, on: :collection

  # i'll be lazy and post to :index
  post :search, action: :index, on: :collection
end

POST 表单提交默认以 TURBO_STREAM 形式发送,并且将呈现 index.turbo_stream.erb

# app/views/users/index.html.erb

<%= form_with url: search_users_path do |f| %>
  <%= f.text_field :search %>
  <%= f.submit %>
<% end %>

<%= tag.div id: :users_index do %>
  <%= render @users %>
<% end %>
# app/views/users/index.turbo_stream.erb

<%= turbo_stream.update :users_index do %>
  <%= render @users %>
<% end %>

测试设置

只需进行简单的设置即可:

rails --version
# Rails 7.0.4

rails new turbo-test -j esbuild
cd turbo-test
bin/rails g scaffold User name
bin/rails db:migrate
open http://localhost:3000/users
bin/dev
# app/controllers/users_controller.rb

def create
  @user = User.new(user_params)

  respond_to do |format|
    if @user.save
      # Add this line:
      format.turbo_stream { render turbo_stream: turbo_stream.prepend(:users, partial: "user", locals: { user: @user }) }

      format.html { redirect_to user_url(@user), notice: "User was successfully created." }
    else
      format.html { render :new, status: :unprocessable_entity }
    end
  end
end
# app/views/users/index.html.erb

# submit form
<%= render "form", user: User.new %>

# new user gets prepended here
<div id="users">
  <%= render @users %>
</div>

关于ruby-on-rails - rails 7 : Turbo stream is showing partial only,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74966556/

相关文章:

ruby-on-rails - 使用链接而不是按钮提交 Rails 4 表单

ruby-on-rails - rmagick 导致服务器关闭

ruby-on-rails - 如何在 Rails 中覆盖 `root_path`?

ruby-on-rails - Mongoid 相当于 create_with

ruby-on-rails - 限制向用户发送大量消息的 "rails way"是什么?

ruby-on-rails - Ruby on Rails - 哈希数组 - 基于键显示值

ruby-on-rails - 在 Rails before_save 方法中将多个属性大写

ruby-on-rails - 使用设备发送密码更改确认

ruby-on-rails - ENV 变量中的 Capistrano 和 API key ?

ruby-on-rails - “field-with-errors” 可以附加到引发错误的输入标签的父级吗?