Skip to content

Instantly share code, notes, and snippets.

@DimaSamodurov
Last active September 12, 2016 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DimaSamodurov/3a339dd248edfec38249ec42132103c1 to your computer and use it in GitHub Desktop.
Save DimaSamodurov/3a339dd248edfec38249ec42132103c1 to your computer and use it in GitHub Desktop.
ActiveAdmin + reorder index table using jQuery.sortable
ActiveAdmin.register Category do
index do
reorderable_column(self)
column :name
end
controller do
private
def reorderable_column(dsl)
dsl.column('Reorder', sortable: false) do
dsl.fa_icon :arrows, class: "js-reorder-handle"
end
end
helper_method :reorderable_column
end
collection_action :reorder, method: :patch do
positions = params.require(:positions)
# TODO: add validation e.g. require each position is uniq: positions.values.uniq.size == positions.size
# TODO: do not allow reordering if Filtering, Pagination or Sorting is applied.
resource_class.transaction do
positions.each do |id, position|
item = resource_class.find_by(id: id)
new_position = position.to_i + 1
item.update_column(:position, new_position) if item.position != new_position
end
end
render json: { status: "success" }
end
end
module ActiveAdmin
module Views
# Adds data-id attribute to the <tr> tag rendering ActiveAdmin index tables
module TableForData
def build_table_body
@tbody = tbody do
# Build enough rows for our collection
@collection.each do |elem|
classes = [cycle('odd', 'even')]
if @row_class
classes << @row_class.call(elem)
end
tr(class: classes.flatten.join(' '), id: dom_id_for(elem), 'data-id': id_for(elem))
end
end
end
private
def id_for(record)
record.id if record.respond_to?(:id)
end
end
end
end
ActiveAdmin::Views::TableFor.prepend ActiveAdmin::Views::TableForData
$(document).ready(function () {
$(".sortable tbody").sortable({
update: function () {
$.ajax({
url: "/admin/categories/reorder",
type: 'patch',
data: serializePositions(this),
complete: function () {
}
});
}
});
var serializePositions = function (items_container) {
var result = {};
$.each($(items_container).find('tr'), function (i, elem) {
result[$(elem).data('id')] = i;
});
return {positions: result};
};
});
class AddPosition < ActiveRecord::Migration
MODELS = [Category, Model2, Model3]
def up
MODELS.each do |model|
add_column model.table_name, :position, :integer, index: true
model.all.each_with_index { |item, index| item.update_column(:position, index + 1) }
end
end
def down
MODELS.each do |model|
remove_column model.table_name, :position
end
end
end
@DimaSamodurov
Copy link
Author

Example implies:
You are using ActiveAdmin, models with a few (dozen) of records max, no Paging, Filtering or Ordering is applied.

Note:
URL "/admin/categories/reorder" could also be parameterized, then the whole approach could take defaults, with a single required configuration setting: reorderable_models = [Categoy, Model2, Model3] .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment