Sortable Bootstrap Tables (in Rails)
Sau đây mình xin giới thiệu cho các bạn một gem trong rails hỗ trợ các bạn trong việc sắp xếp và thay đổi thứ tự các bản ghi trong danh sách các bản ghi. Nó sẽ hỗ trợ các bạn kéo thả bằng việc sử dụng thư viện của JQuery ( JQuery UI Gem) làm việc sắp xếp trở nên sinh động và dễ dàng hơn. Nào hãy ...
Sau đây mình xin giới thiệu cho các bạn một gem trong rails hỗ trợ các bạn trong việc sắp xếp và thay đổi thứ tự các bản ghi trong danh sách các bản ghi. Nó sẽ hỗ trợ các bạn kéo thả bằng việc sử dụng thư viện của JQuery ( JQuery UI Gem) làm việc sắp xếp trở nên sinh động và dễ dàng hơn. Nào hãy cùng tìm hiểu cách sử dụng nó nhé, nó cũng không quá khó để cài đặt.
I. Tổng quan
Bài viết sẽ giúp các bạn làm sao để thêm sắp xếp bằng cách kéo thả vào bảng trong rails. Ở đây chúng ta sử dụng ranked-model và JQuery-UI
II. Sortable list gems
ranked.rb
def update_index_from_position case position when Integer neighbors = neighbors_at_position(position) min = (neighbors[:lower] ? neighbors[:lower].rank : RankedModel::MIN_RANK_VALUE) max = (neighbors[:upper] ? neighbors[:upper].rank : RankedModel::MAX_RANK_VALUE) rank_at( ( ( max - min ).to_f / 2 ).ceil + min ) end end
ranked-model thực hiện bằng cách tăng thứ hạng nằm giữa khoảng từ -8388607 đến 8388607 (mở rộng của MEDIUMMINT trong MySQL). Điều gì sẽ xảy ra nếu sau vài nghìn lần sắp xếp một danh sách các số được sắp xếp thứ tự sẽ gối lên nhau, hoặc chúng sẽ vượt ra khỏi giới hạn? Trong trường hợp này, tất cả bảng sẽ được cập nhật...
ranked.rb
def assure_unique_position if ( new_record? || rank_changed? ) unless rank rank_at( RankedModel::MAX_RANK_VALUE ) end if (rank > RankedModel::MAX_RANK_VALUE) || current_at_rank(rank) rearrange_ranks end end end
Nói một cách thực tế, nếu số lượng sắp xếp trên web của bạn không quá nhiều thì vấn đề này hoàn toàn có thể được giải quyết. Tuy nhiên, ranked-model khá dễ dàng để cài đặt và không có lý do gì để chúng ta không sử dụng nó.
III. Cài đặt
Cài đặt gem và thêm trường vào model. Gemfile
gem "ranked-model"
models/thing.rb
class Thing < ActiveRecord::Base include RankedModel ranks :row_order end
db/migrate/20140908010519_add_row_order_to_things.rb
class AddRowOrderToThings < ActiveRecord::Migration def change add_column :things, :row_order, :integer end end
Update Row Order Controller Action Đầu tiên chúng ta cần viết hàm để cập nhật việc sắp xếp row_order_position. Nó sẽ cần số thứ tự và id của model cần sắp xếp. Chúng ta sẽ làm rõ ở phần gửi chúng qua AJAX POST ở phần sau.
controllers/admin/things_controller.rb
class ThingsController < ApplicationController def index @things = Thing.rank(:row_order).all end def update_row_order @thing = Thing.find(thing_params[:thing_id]) @thing.row_order_position = thing_params[:row_order_position] @thing.save render nothing: true # this is a POST action, updates sent via AJAX, no view rendered end private # Use callbacks to share common setup or constraints between actions. def set_thing @thing = Thing.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def thing_params params.require(:thing).permit(:thing_id, :title, :description, :row_order_position) end end
Thêm route cho sort config/routes.rb
resources :things do post :update_row_order, on: :collection end
Bây giờ, chúng ta sẽ thêm JavaScript để kéo thả sử dụng JQuery UI Gem Chúng ta cần sortable và highlight modules.
assets/javascripts/admin/application.js
//= require jquery //= require jquery_ujs //= require jquery-ui/sortable //= require jquery-ui/effect-highlight //= require turbolinks //= require_tree .
assets/javascripts/admin/update_things_row_order.js.coffee
jQuery -> if $('#sortable').length > 0 table_awidth = $('#sortable').awidth() cells = $('.table').find('tr')[0].cells.length desired_awidth = table_awidth / cells + 'px' $('.table td').css('awidth', desired_awidth) $('#sortable').sortable( axis: 'y' items: '.item' cursor: 'move' sort: (e, ui) -> ui.item.addClass('active-item-shadow') stop: (e, ui) -> ui.item.removeClass('active-item-shadow') # highlight the row on drop to indicate an update ui.item.children('td').effect('highlight', {}, 1000) update: (e, ui) -> item_id = ui.item.data('item-id') position = ui.item.index() # this will not work with paginated items, as the index is zero on every page $.ajax( type: 'POST' url: '/things/update_row_order' dataType: 'json' data: { thing: {thing_id: item_id, row_order_position: position } } ) )
Table Markup Bây giờ, chúng ta sẽ thêm bootstrap table markup. Mỗi hàng của bảng có 1 class của đối tượng chỉ định trong tùy chọn của JQuery UI sortable. Thing.id thích hơpj sẽ được thêm vào mỗi hàng và truyền vào update_row_controller.
views/admin/things/index.html.erb
<table class="table table-bordered table-striped" id="sortable"> <thead> <tr> <th> Title </th> <th> Description </th> </tr> </thead> <tbody> <% @things.each do |thing| %> <tr data-item-id=<%= thing.id %> class="item"> <td> <%= thing.title %> </td> <td> <%= link_to "show", thing_path(thing), class: "btn btn-default pull-right" %> </td> </tr> <% end %> </tbody> </table>
Vậy là chúng ta đã có thể sắp xếp trong bảng chỉ với một số cài đặt đơn giản. Mong rằng bài viết này có thể giúp các bạn có thêm những lựa chọn cho việc sắp xếp dữ liệu. Các bạn có thể xem thêm tại:
Live demo
Github repo
Chúc các bạn thành công.