ruby-on-rails (Rails)Turbostream在Stimulus请求后不更新视图部分中的svg

3duebb1j  于 2023-04-13  发布在  Ruby
关注(0)|答案(1)|浏览(271)

我想单击一个SVG图标,触发一个Stimulus操作,该操作在后端更新我的模型(trx)的“cleared”属性,然后更新视图以显示一个不同的SVG图标,指示trx已清除,而不刷新页面。
最初,我的view partial根据模型的“cleared”值(如果trx.cleared?)显示正确的SVG。

  • app/views/trxes/_trx.html.erb*
<div id="<%= dom_id trx %>" data-controller="trx-toggle" data-trx-toggle-url-value="<%= trx_path(trx) %>" data-trx-toggle-cleared-value="<%= trx.cleared %>">
...
  <div>
    <% if trx.cleared? %>
      <%= inline_svg_tag "icons/cleared_closed.svg", class: "h-6 w-6 fill-green-500", aria_hidden: true, data: { action: "click->trx-toggle#toggleCleared", trx_toggle_target: "cleared"} %>
    <% else %>
      <%= inline_svg_tag "icons/cleared_open.svg", class: "h-6 w-6 fill-green-500", aria_hidden: true, data: { action: "click->trx-toggle#toggleCleared", trx_toggle_target: "cleared" } %>
    <% end %>
  </div>
...
</div>

正确单击图标会触发此Stimulus操作,该操作会在参数中发送相反的布尔值

  • trx切换控制器.js*
...
toggleCleared() {
    let formData = new FormData()
    formData.append("trx[cleared]", !this.clearedValue) // "true" or "false"
    const token = document.getElementsByName("csrf-token")[0].content;
    fetch(this.urlValue,{
      body:formData,
      method: 'PATCH',
      dataType: 'script',
      credentials: 'include',
      headers: {
        "X-CSRF-Token": token,
        "Accept": "text/vnd.turbo-stream.html, text/html, application/xhtml+xml"
      },
    })
  }
...

它似乎发送了正确的参数,并正确地更新了记录(日志输出)

Started PATCH "/trxes/123" for 127.0.0.1 at 2023-04-07 22:31:38 -0700
Processing by TrxesController#update as TURBO_STREAM
  Parameters: {"trx"=>{"cleared"=>"true"}, "id"=>"123"}
  ...
  Trx Update (0.3ms)  UPDATE "trxes" SET "updated_at" = ?, "cleared" = ? WHERE "trxes"."id" = ?  [["updated_at", "2023-04-08 05:31:38.761532"], ["cleared", 1], ["id", 123]]
  ↳ app/controllers/trxes_controller.rb:45:in `block in update'
  ...
  Rendered trxes/_trx.html.erb (Duration: 7.4ms | Allocations: 2233)
Completed 200 OK in 24ms (Views: 0.2ms | ActiveRecord: 5.2ms | Allocations: 8649)
  • app/controllers/trxes_controller.rb*
def update
  trx(new_trx_params)
  respond_to do |format|
    if trx.save!
      format.turbo_stream { render turbo_stream: turbo_stream.replace(
        helpers.dom_id(trx),
        partial: 'trx',
        locals: { trx: trx }
      ) }
      format.html { render_to_string(partial: 'trx', locals: {trx:trx }) }
    else
      trx.errors.full_messages.each do |e|
        puts "DEBUG Trx Error: #{e}"
      end
      render :new
    end
  end
end

记录更新了,一个新的JS请求在我的浏览器的NETWORK选项卡上可见,但我需要刷新页面才能看到更新的图标。
我有一个用于编辑整个trx记录的幻灯片表单,它不需要刷新页面就可以工作。我看到的唯一区别是在NETWORK选项卡中:它显示了由turbo. min...用CONTENT-TYPE: application/x-www-form-urlencoded;charset=UTF-8发起的POST请求。而我的刺激控制器请求是由trx_toggle_controller...和CONTENT-TYPE: multipart/form-data; boundary=---------------------------419727981959891446676073942发起的PATCH

icnyk63a

icnyk63a1#

我只展示一个简单的例子,也许它会给予你一些关于如何避免手动获取请求的新想法,很多时候它是不需要的:

// app/javascript/controllers/hello_controller.js

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["item"];

  // do something when new item shows up
  // no manual fetching
  itemTargetConnected(target) {
    document.querySelector("#item-updater").innerHTML = this.itemTargets.length;
  }
}
# app/controllers/items_controller.rb

def create
  render turbo_stream: turbo_stream.append(
    "items", '<div data-hello-target="item">1</div>'
  )
end
<!-- app/views/home/index.html.erb -->

<div id="item-updater"></div>

<div id="items" data-controller="hello">
</div>

<%= button_to "create", "/items" %>
  • 网址:http:stimulus.hotwired.dev/reference/targets#connected-and-disconnected-callbacks*

您还可以渲染多个turbo流:

def create
  render turbo_stream: helpers.safe_join([
    turbo_stream.append("items", '<div data-hello-target="item">1</div>'),
    turbo_stream.before("item-updater", '<p>updated</p>')
  ])
end

相关问题