为了账号安全,请及时绑定邮箱和手机立即绑定

Rails Rails 用 RJS 简单有效的实现页面局部刷新

标签:
Ruby

我们时常在做项目的时候会遇到这样的需求,页面上有个基本数据的下拉框,用于选择一些数据,如:项目版本号、联系人、收件地址、银行账号列表什么的。

而需求可能会要求说可以在这个页面随时增加那些下拉框的选择值,而不是另开窗口。

于是我们可能需要实现一个浮动窗口,里面包含新增表单,实现表单 AJAX 提交,最后在刷新主窗口的下拉菜单控件。

这里介绍一下我最近实现的一个简单方式:

主表单页面:

link_to + remote 的方式实现一个 Ajax 请求的点击

<div class="form-field-user-address">
  <%= f.select :address, collection: current_user.addresses %>
</div>
<%= link_to '新增联系地址', new_address_path, remote: true %>

AddressesController 保持标准的 Rails new 函数结构

class AddressesController < ApplicationController
  def new
    @address = Address.new
  end

  def create
    @address = Address.new(address_params)
    respond_to do |format|
      if @address.save
        format.html { redirect_to addresses_path, notice: '地址新增成功。' }
        format.js
      else
        format.html { render :new }
        format.js
      end
    end
  endend

新增 new.js.erb (以后会大量用 js.erb 的做法),由于前面是 remote 请求,HTTP Header 里面带的信息会让 Rails 渲染 js.erb 的模板 这里渲染 _form.html.erb 生成地址表单的 HTML:

var html = "<%= j(render('form', remote: true)) %>";// bootbox 弹窗插件 http://bootboxjs.com/bootbox.dialog({
  title: "新增联系地址",
  message: html});

然后我们就得到了这样的界面:

https://img1.sycdn.imooc.com//5c4960cf000135d205390337.jpg

https://img1.sycdn.imooc.com//5c4960ec0001cad105440402.jpg

然后正题来了,我们怎样才能在地址新增成功以后,以无刷新的方式更新主表单上面那个下拉框呢?

https://img1.sycdn.imooc.com//5c496112000126ce07360156.jpg

这就是本帖要将的技巧,非常简单,而且适用于任何地方!

我们新增一个 create.js.erb,前面说过 remote 的请求,Rails 会选择 js.erb 的模板来渲染

<% if @address.errors.blank? %>
  // 用 Ajax 载入当前页面,找到下拉框的 Dom 的新 HTML,再替换目前页面的下拉框 Dom
  var selector = '.form-field-user-address';
  $.get(location.href, function(html) {
    var doc = $(html).find(selector);
    $(selector).replaceWith(doc);
  });
  bootbox.hideAll();<% else %>
  var html = "<%= j(render('form', remote: true)) %>";
  // 保存失败,直接替换浮动窗口上面的 HTML 为新的 form render 结果
  // 因为 @address 包含验证错误信息,所以 render 出来的 HTML 也包含验证信息
  $('form.new_address').replaceWith(html);<% end %>

为了很多地方都能用到,于是我把上面的变成一个公共函数:

app.coffee

window.App =
  refreshDom: (selector) ->
    $.get location.href, (html) ->
        doc = $(html).find(selector)
        $(selector).replaceWith(doc)

create.js.erb 就可以简化了:

<% if @address.errors.blank? %>
  App.refreshDom('.form-field-user-address');
  bootbox.hideAll();<% else %>
  var html = "<%= j(render('form', remote: true)) %>";
  $('form.new_address').replaceWith(html);<% end %>


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消