【问题标题】:Render New/Create and Edit/Update form on same page在同一页面上呈现新/创建和编辑/更新表单
【发布时间】:2019-08-10 08:25:59
【问题描述】:

我有两个控制器,BoardsSectionsSections 嵌套在Boards 中,一个Board 可以有多个Sections。在 Boards 的 Show 页面上,我希望能够创建一个新的 Section 并对其进行编辑。

目前我有在Boards 显示页面上创建一个新的Section 的表单,但我还没有找到将这个表单重用于编辑方法的方法。

Boards#show

<%= render 'sections/shared/form', board: @board, section: @section %>
<br>

<% @board.sections.order(id: :asc).each_with_index do |section, index| %>
  <%= "#{index + 1}. #{section.title}" %>
  <% if policy(section).edit? %>
    <%= link_to "Edit", edit_board_section_path(@board, @board.sections[index]) %>
  <% end %>
  <% if policy(section).destroy? %>
    <%= link_to("Delete", board_section_path(@board, @board.sections[index]), method: :delete) %>
  <% end %>
  <br>
<% end %>

表格部分

<%= simple_form_for([@board, @section]) do |f| %>
  <%= f.input :title %>
  <%= f.submit "Save" %>
<% end %>

edit_board_section_path 基本上复制了部分表单。

如何使某个部分旁边的“编辑”按钮允许我在 Boards#show 页面本身上编辑一个部分?我不想重新连接到另一个页面来编辑表单,而是直接在 Boards#show 上显示它。

【问题讨论】:

  • 你能显示你当前的编辑模板吗?
  • @arieljuod 这是编辑模板:&lt;%= simple_form_for([@board, @section]) do |f| %&gt; &lt;%= f.input :title %&gt; &lt;%= f.submit "Save changes" %&gt; &lt;% end %&gt;
  • 我没有得到你想要达到的目标。为什么不能只在编辑模板上渲染部分?
  • 对不起,我可能没说清楚。我只想在用户单击“编辑”后在 Boards#show 页面上显示编辑模板。理想情况下,我不想重定向到另一个页面,而是在单击“编辑”后让此编辑表单直接出现在当前页面上。
  • 我添加了一个按钮/javascript 来显示切换编辑表单的样子

标签: javascript ruby-on-rails ajax forms


【解决方案1】:

您需要将表单部分更改为使用传入的变量boardsection,而不是前缀为@ 的变量。添加remote: true 将允许您通过 AJAX 提交。

<%= simple_form_for([board, section], remote: true) do |f| %>
  <%= f.input :title %>
  <%= f.submit "Save" %>
<% end %>

进行该更改后,新部分的渲染仍将像您当前一样工作。要为每个现有部分添加编辑表单,您可以执行以下操作:

<%# index.html.erb %>
<div id="sections">
    <% @board.sections.order(id: :asc).each_with_index do |section, index| %>
            <%= render partial: 'sections/section', section: section, index: index %>
    <% end %>
</div>

<script>
window.addEventListener("click", function(event) {
    if (event.target.matches('.edit-form-toggle')) {
        event.target.parentElement.querySelector('.edit-form').classList.toggle('hidden');
    }
});
</script>
<style>
.hidden { display: none; }
</style>

<%# sections/_section.html.erb %>
<div id="section-<%= section.id %>
    <%= "#{index + 1}. #{section.title}" %>
    <% if policy(section).edit? %>
        <button class="edit-form-toggle">Edit</button>
        <div class="edit-form hidden">
            <%= render 'sections/shared/form', board: section.board, section: section %>
        </div>
    <% end %>

    <% if policy(section).destroy? %>
        <%= link_to("Delete", board_section_path(section.board, sections.id), method: :delete) %>
    <% end %>
</div>

如果您使用的是浅层路线,则 board 变量应该是 nil,如果不是,则在 per-section edit form partial 中应该是 @board

您需要在控制器中处理不同的响应格式:

class SectionsController < ApplicationController

    def create
        @board = Board.find(params[:board_id]
        @section = board.sections.build(section_params)

        respond_to do |format|
            if @section.save
                format.html { redirect_to @board }
                format.js # renders app/views/sections/create.js.erb
            else
                format.html {}
                format.js
            end
        end
    end

    def update
        @section = Sections.find(params[:id])

        respond_to do |format|
            if @section.update(section_params)
                format.html { redirect_to section.board }
                format.js # renders app/views/sections/update.js.erb
            else
                format.html {}
                format.js
            end
        end
    end


    def section_params
        ...
    end
end

还有你的看法:

// create.js.erb
<% if @section.errors %>
    alert('could not save section');
<% else %>
    // clear new form, append new section
    document.getElementById('new_section').querySelector('input[name="section[name]"').value = "";
    document.getElementById('sections').innerHTML += "<%= j(render 'section', section: @section, index: @section.board.sections.count -1) %>"
<% end %>

// update.js.erb
<% if @section.errors %>
    alert('could not save section');
<% else %>
    alert('saved section');
<% end %>

【讨论】:

  • 感谢您的有用评论。当您单击该特定部分的“编辑”时,我实际上只想显示该部分的编辑表单。目前显示所有编辑表单,并且我在任何一种表单中所做的更改仅在我重新加载页面后应用
  • 我添加了一个示例 css 样式以隐藏到非编辑表单(是 .hidden 类)和一个简单的控制器/视图示例,您需要处理添加了 Ajax 支持的部分表单在表单上使用 remote: true 时。我还提取了该部分的视图部分,以便您可以在普通页面上使用它并在create.js.erb 模板中重复使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
相关资源
最近更新 更多