世界上最伟大的投资就是投资自己的教育

首页Ruby
Mikasa·Ackerman · 真仙

如何在 Rails 中添加拖拽排序

Mikasa·Ackerman发布于3343 次阅读

准备

需要使用的 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 条回复
喜欢
统计信息
    学员: 29960
    视频数量: 1996
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top