远程:在简单表单上为 true,不发出 AJAX 请求,而是呈现空白页

Remote: true on simple form not making AJAX request but rendering blank page instead

提问人:Lisbeth Purrucker 提问时间:3/20/2023 最后编辑:Lisbeth Purrucker 更新时间:3/22/2023 访问量:463

问:

我知道有很多关于这个问题的帖子,但其中大多数都非常老,没有一个包括 ActionCable。因此,挑战来了:

我正在使用 ActionCable 构建聊天功能,并且消息已成功广播。消息也会立即呈现给接收方,但在发送方端,会像往常一样为发布请求(消息创建表单)呈现空白页。我收到一个,我在消息创建方法中触发了它,但我显然想保持在同一页面上并通过 JS(使用 Stimulus for JS)插入 HTML。status code of 200

app/views/chats/show.html.erb - 创建消息的表单

 <%= simple_form_for [@chat, @message], remote: true,
    html: {
      class: 'chat__form',
      data: {
        action: "turbo:submit-end->chat-subscription#resetForm"
      }
    } do |f| %>
      <%= f.input :content,
                  label: false,
                  placeholder: "Message ##{@name}",
                  input_html: { class: 'chat__form-input' } %>
      <%= button_tag(class: 'chat__form-button') do %>
        <%= image_tag('icons/send.svg') %>
      <% end %>
  <% end %>

app/controllers/messages_controller.rb - 创建方法

def create
    @chat = Chat.find(params[:chat_id])
    @message = Message.new(message_params)
    @message.chat = @chat
    @message.user = current_user
    if @message.save
      ChatChannel.broadcast_to(
        @chat,
        render_to_string(partial: "messages/message", locals: {message: @message})
      )
      head :ok
    end
  end

应用程序/javascript/控制器/chat_subscription_controller.js

import { Controller } from "@hotwired/stimulus"
import { createConsumer } from "@rails/actioncable"

export default class extends Controller {
  static values = { chatId: Number }
  static targets = ['messages', 'form']

  connect() {
    this.channel = createConsumer().subscriptions.create(
      { channel: 'ChatChannel', id: this.chatIdValue },
      { received: data => this.#insertMessageAndScrollDown(data) }
    )
    console.log(`Subscribed to the chat with the id ${this.chatIdValue}.`)
    console.log(this.messagesTarget)
  }

  #insertMessageAndScrollDown(data) {
    this.messagesTarget.insertAdjacentHTML('beforeend', data)
    this.messagesTarget.scrollTo(0, this.messagesTarget.scrollHeight)
  }

  resetForm(event) {
    event.preventDefault()
    event.target.reset()
  }

  disconnect() {
    console.log('Unsubscribed from the chat')
    this.channel.unsubscribe()
  }
}

正如我所说 - 这一切都在接收器端完美运行。因此,我可以确保频道设置正确,并且我的 JS 方法也有效。我认为 remote: true 没有触发,并且表单是在本地提交的。我只是不知道我的设置缺少什么。我相信因为我使用的是 Vite 而不是 Webpacker,所以有些东西设置不正确。但我也找不到任何资源。

那么redis呢,它是如何发挥作用的?

Ruby-on-Rails Ajax Vite Ruby-on-Rails-7 远程表单

评论

0赞 max 3/20/2023
忘掉.在 Rails 7 应用程序中,您不需要也不需要 Rails UJS 或 jQuery UJS。两者都已经过时了(jQuery早在2016年就被抛弃了),而Turbo提供了以前由Rails UJS提供的功能。remote: true
0赞 Lisbeth Purrucker 3/20/2023
你对实现我想要实现的目标有什么建议?
0赞 max 3/20/2023
我会找到一些关于如何使用 Turbo 及其概念进行 CRUD 的基本教程,然后当您掌握这些教程时,弄清楚如何将其与 ActionCable 集成。我认为,如果你试图同时学习这两样东西,你的大脑就会爆炸。还要忘记“本地”和“远程”这两个术语——命名是 Rails UJS 最糟糕的部分,它不是推理同步和异步请求的好方法。
0赞 Lisbeth Purrucker 3/20/2023
你能给我反馈一下我对 Vite 的使用情况吗?每次我渲染一个页面(比如说从索引页到一个节目)时,如果将 Turbo 正确添加到项目中,我都希望发生一个 fetch 请求。是吗?因为它没有发生。它正在发出 HTML 请求。
0赞 max 3/20/2023
对不起,我什至从未听说过。如果你只是为了学习而这样做,我会坚持使用默认的 Rails 工具链。无论如何,都足以让你头晕目眩。

答:

1赞 Alex 3/22/2023 #1

我快速尝试了一下,这是一个工作设置:

rails new hello_vite --skip-javascript
cd hello_vite

bundle add turbo-rails stimulus-rails
mkdir app/javascript
bin/rails turbo:install:node
bin/rails stimulus:install:node

bundle add vite_rails
bundle exec vite install

bin/rails g scaffold Chat
bin/rails g scaffold Message content:text
bin/rails g channel Chat
bin/rails g stimulus chat_subscription
bin/rails db:migrate
bin/rails runner Chat.create
bin/vite dev
bin/rails s

仅此而已。也许你缺少 gem,所以服务器无法识别TURBO_STREAM格式,请在 rails 控制台中检查:turbo-rails

>> Mime[:turbo_stream]
=> #<Mime::Type:0x00007f15104567e0 @hash=-2016241814324581175, @string="text/vnd.turbo-stream.html", @symbol=:turbo_stream, @synonyms=[]>

# app/javascript/entrypoints/application.js
import "@hotwired/turbo-rails"
import "../controllers"

# app/controllers/messages_controller.rb
def create
  @chat = Chat.first
  @message = Message.new(message_params)
  if @message.save
    ChatChannel.broadcast_to(@chat, render_to_string(@message))
    head :ok
  end
end

# app/channels/chat_channel.rb
def subscribed
  stream_for Chat.find(params[:id])
end

# app/views/messages/index.html.erb
<%= tag.div data: {
  controller: "chat-subscription",
  chat_subscription_chat_id_value: Chat.first.id
} do %>
  <%= render "form", message: Message.new %>
  <%= tag.div id: :messages, data: {chat_subscription_target: :messages} do %>
    <%= render @messages %>
  <% end %>
<% end %>

# app/views/messages/_form.html.erb
<%= form_with model: message,
  data: { action: "turbo:submit-end->chat-subscription#resetForm" },
  html: { style: "position:sticky;top:0;background-color:white;" } do |form| %>
  #       ^^^^^^^^ this is just to test the auto scroll ^^^^^^^^
  <%= form.text_area :content, placeholder: "message..." %> <br>
  <%= form.submit %>
<% end %>

# app/javascript/controllers/chat_subscription_controller.js
import { Controller } from "@hotwired/stimulus";
import { createConsumer } from "@rails/actioncable";
export default class extends Controller {
  static values = { chatId: Number };
  static targets = ["messages"];
  connect() {
    this.channel = createConsumer().subscriptions.create(
      { channel: "ChatChannel", id: this.chatIdValue },
      { received: (data) => this.insertMessageAndScrollDown(data) }
    );
  }
  insertMessageAndScrollDown(data) {
    this.messagesTarget.insertAdjacentHTML("beforeend", data);
    this.messagesTarget.scrollIntoView({ behavior: "smooth", block: "end" });
  }
  resetForm(event) {
    event.target.reset();
  }
  disconnect() {
    this.channel.unsubscribe();
  }
}

评论

0赞 Lisbeth Purrucker 3/22/2023
嘿,亚历克斯!非常感谢,我很感激你的努力。不过,我确实安装了 Turbo-Rails Gem,也是进口的。目前,我没有时间迁移回 VITE 来检查它。我将在不久的将来对其进行测试,如果我能让它进入工作状态,请接受您的回答。谢谢!