首页ruby

如何在 Rails 中添加拖拽排序

Marin发布于796 次阅读

准备

需要使用的gem

gem 'acts_as_list'
gem 'jquery-ui-rails'

需要的js文件

//= require jquery-ui/jquery-ui.js

页面添加想要排序的列表

<table class="table table-bordered table-hover">
  <thead>
    <th>视频编号</th>
    ...
    <th>操作</th>
  </thead>
  <tbody data-url="<%= sort_admin_round_manage_good_videos_path %>" data-behavior='sortable'>
    <% @good_videos.each_with_index do |g, index| %>
      <tr id="<%= dom_id(g) %>">
        <td><%= g.id %></td>
        ...
        <td><%= operate_buttons(good_video_operation(g)) %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<script>
$( "[data-behavior='sortable']" ).sortable({
  update: function(e, ui) {
    $.ajax({
      url: $(this).data("url"),
      type: "PATCH",
      data: $(this).sortable('serialize')
    })
  }
});

</script>

第一种方式我们将排序后的序列整体发送到后台,后台需要添加响应的排序字段

rails g migration AddPositionToGoodVideo position:integer
rails db:migrate

控制器添加列表和排序action

def index
  @q = GoodVideo.ransack(params[:q])
  @good_videos = @q.result.order(position: :desc)
end

# 这里使用第一种排序方式(优点:如果position值为空或者0,在经过之后将会按排序赋值,缺点:每次排序根据当前页面数据量生成大量sql,大量操作不建议使用。)
def sort
  params[:good_video].reverse.each_with_index do |id, index|
    GoodVideo.find_by(id: id).update(position: index + 1)
  end
  head :ok
end

路由配置

resources :good_videos do
  collection do
    patch :sort
  end
end

总结:第一种方法 这样既可实现拖拽排序(这种方法弊端:如果有分页的话第二页的排序会有问题,所以这种排序是不可以有分页的,所有数据只能在一个页面,也就限制了不适用太大的数据量和频繁的操作。)

第二种方法

页面基本保持一致 js 有一些变化,这里我们获取了当前拖拽元素id释放后的位置的前后元素的id

$( "[data-behavior='sortable']" ).sortable({
  update: function(e, ui) {
    params = "prev_id=" + $(ui.item[0]).prev().attr("id").split("_")[2] + "&id=" + $(ui.item[0]).attr("id").split("_")[2] + "&next_id=" + $(ui.item[0]).next().attr("id").split("_")[2];
    $.ajax({
      url: $(this).data("url"),
      type: "PATCH",
      data: params
    })
  }
});

排序方法也有相应修改并且position字段应采用decimal类型长度应尽量长一些,防止因长度不够,而造成多个position 都为 0.00的情况;对移动到第一位,或者最后一位做if处理。

def sort
  good_video = GoodVideo.find(params[:id])
  next_task = params[:next_id] && GoodVideo.find(params[:next_id])
  prev_task = params[:prev_id] && GoodVideo.find(params[:prev_id])
  position = if params[:prev_id].blank?
               next_task.position / 2
             elsif params[:next_id].blank?
               prev_task.position + 100000
             else
               (prev_task.position + next_task.position) / 2
             end
  good_video.update(position: position)
end

总结:第二种方法排序生成的sql更少,仅仅通过上一位置和下一位置来生当前选择元素的排序值。分页的话也不会有问题,不过对于很多初始值就是0.0的排序来将不会给赋值,要手动拖拽后才会生成排序值。

本站文章均为原创内容,如需转载请注明出处,谢谢。

1 条回复
喜欢
友情提示
   官方 QQ 群 697272886

© Rails365 | 隐私条款 | 服务条款 | 加盟本站 | 粤ICP备15004902号 | 在线学员:6

Top