You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5.2更新操作失败后如何在模态框中重新渲染编辑表单

问题原因

当前表单默认是整页同步提交,更新失败后后端直接返回edit视图内容,浏览器会将其作为独立页面加载,不会自动包裹在原有模态框容器中。

实现方案

推荐用Rails原生的异步提交(AJAX)方案,不需要大幅改动现有代码,体验也更流畅:

  • 第一步:调整表单配置,开启异步提交,给模态框内容加固定容器方便替换
    编辑表单部分代码,明确指定异步提交,外层套上带固定ID的容器:
<div id="schedule-edit-modal-content">
<%= form_with model: [namespace, @production_job, @production_schedule], 
              local: false,
              html: { id: "edit_form" } do |f| %>
  <!-- 原有modal-header、modal-body、modal-footer代码完全保留,不需要修改 -->
<% end %>
</div>
  • 第二步:调整控制器update方法的响应逻辑
    重点是校验失败时不要渲染带布局的页面,同时新增js格式响应:
# PATCH/PUT /production_schedules/1 or /production_schedules/1.json
def update
  @production_job = ProductionJob.find(@production_schedule.production_job_id)
  Rails.logger.interactions.info "Schedule update - id: #{@production_schedule.id},
                                  code: #{@production_schedule.code},
                                  mode: #{@production_schedule.mode.code}"
  if @production_schedule.mode.code == 'TEST' or @production_schedule.mode.code == 'MESSAGE'
    @production_schedule.next_run = nil
  end
  respond_to do |format|
    if @production_schedule.update(production_schedule_params)
      json_parameters_serialization(@production_schedule)
      @production_schedule.update_attribute(:status_id, statuses.find { |x| x["code"] == "READY" }.id || 0)
      format.html { redirect_to scheduler_production_job_path(@production_job), notice: "Production schedule was successfully updated." }
      format.json { render :show, status: :ok, location: @production_schedule }
      format.js
    else
      @production_schedule.update_attribute(:status_id, statuses.find { |x| x["code"] == "INACTIVE" }.id || 0)
      # 注意这里加上layout: false,不要渲染全局布局
      format.html { render :edit, layout: false, status: :unprocessable_entity }
      format.json { render json: @production_schedule.errors, status: :unprocessable_entity }
      format.js { render status: :unprocessable_entity }
    end
  end
end
  • 第三步:新增JS响应模板
    在app/views/production_schedules/目录下新建update.js.erb文件,处理提交成功/失败的前端逻辑:
<% if @production_schedule.errors.none? %>
  // 提交成功:关闭模态框,跳转回列表页
  $("#childModal").modal("hide");
  window.location.href = "<%= scheduler_production_job_path(@production_job) %>";
<% else %>
  // 提交失败:替换模态框内容为带错误提示的表单,保持模态框打开
  document.getElementById("schedule-edit-modal-content").innerHTML = "<%= j render "form", production_schedule: @production_schedule, production_job: @production_job %>";
<% end %>
  • 第四步:确认Rails UJS依赖
    检查app/javascript/application.js(旧版本是app/assets/javascripts/application.js)中是否引入了rails-ujs,没有的话补上即可,这是Rails原生支持异步提交、表单CSRF校验的基础依赖。

如果不想写前端JS,也可以用重定向方案:更新失败时把当前编辑的调度项ID、错误信息存入flash,重定向回调度计划索引页,页面加载时检测到flash参数就自动打开对应项的编辑模态框,同时渲染错误信息。这种方案多一次页面跳转,体验稍差,不需要额外写JS响应模板。


内容的提问来源于stack exchange,提问作者user1185081

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 00:45:36