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
相关产品推荐
相关产品推荐

