Add the following to Gemfile then run bundle to install them.
- gem 'jquery-rails', '~> 4.3', '>= 4.3.5'
- gem 'jquery-ui-rails', '~> 6.0', '>= 6.0.1'
- gem 'rails_sortable'
Next =>
Add the following to the asset pipeline in the application.js:
//= require jquery
//= require jquery3
//= require jquery-ui/widgets/sortable
//= require rails_sortable
//= require bootstrap-sprockets
//= require_tree . # will add html.sortable
// Bulletins Drag & Drop Sortable
$(function () {
$('.sortable').railsSortable();
});
Next =>
app/assets/javascripts/bulletin.sort.js
let ready = undefined;
let set_positions = undefined;
set_positions = function() {
$('.card').each(function(i) {
$(this).attr('data-pos', i + 1);
});
};
ready = function() {
set_positions();
$('.sortable').sortable();
$('.sortable').sortable().bind('sortupdate', function(e, ui) {
const updated_order = [];
set_positions();
$('.card').each(function(i) {
updated_order.push({
id: $(this).data('id'),
position: i + 1
});
});
$.ajax({
type: 'PUT',
url: '/bulletins/sort',
data: { order: updated_order
}
});
});
};
$(document).ready(ready);
Next =>
app/controllers/bulletins_controller.rb
# GET /bulletins.json
def index
@bulletins = Bulletin.by_position
end
def sort
params[:order].each do |key, value|
Bulletin.find(value[:id]).update(position: value[:position])
end
head :ok
end
Next =>
$ rails g mgration AddSortToBulletins
Add:
class AddSortToBulletins < ActiveRecord::Migration[6.0]
def change
add_column :bulletins, :sort, :integer # add the line
end
end
And
$ rails g mgration AddPositionToBulletins
# You should already have this
add:
class AddPositionToBulletins < ActiveRecord::Migration[6.0]
def change
add_column :bulletins, :position, :integer # add the line
end
end
Run: rails db:migrate
Next =>
app/models/bulletin.rb
class Bulletin < ApplicationRecord
include RailsSortable::Model
set_sortable :sort
def self.by_position
order("position ASC")
end
end
Next =>
config/routes.rb
resources :bulletins do
put :sort, on: :collection
end
Next =>
app/views/bulletins/_bulletin.html.erb
<% @bulletins.each_with_sortable_id do |bulletin, sortable_id| %>
<div class="card" id="inner" data-id="<%= bulletin.id %>">
...other code
</div>
<% end %>
Next =>
app/views/bulletins/index.html.erb
<div class="row toolbar tile <%= "sortable" %>">
<%= render "bulletin", collection: @bulletins %>
</div>
Thats it. Try it out.
Oh you may get this Error:
14:53:42 web.1 | Processing by SortableController#reorder as JSON 14:53:42 web.1 | Parameters: {"rails_sortable"=>["portrack", "portrack"], "sortable"=>{"rails_sortable"=>["portrack", "portrack"]}} 14:53:42 web.1 | Can't verify CSRF token authenticity. 14:53:42 web.1 | Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms | Allocations: 938) 14:53:42 web.1 | 14:53:42 web.1 | 14:53:42 web.1 | 14:53:42 web.1 | ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
To Fix just add in app/assets/javascripts/application.js or within the app/javascript/packs/application.js
$(function () {
$('#loader').hide()
$(document).ajaxStart(function () {
$('#loader').show();
})
// Can be removed
$(document).ajaxError(function () {
alert("Checking if its working...")
$('#loader').hide();
})
// Can be removed End
$(document).ajaxStop(function () {
$('#loader').hide();
});
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
}
});
});
Now it should work with no error.