One of the requested features in our QuickAdminPanel was drag and drop reordering of entries in the Datatables. For now, we’ve decided to create a quick demo project that will show you how to add this functionality.
Here is the result of what we will create – in video format.
In this tutorial, we will assume that your model has an integer field position.
Step 1. Setting the position for new entries
If you have app/Devise.php model and you want to add a new currency, here is the code to add:
class Currency extends Model
{
// ...
protected static function boot()
{
parent::boot();
Currency::creating(function ($model) {
$model->position = Currency::max('position') + 1;
});
}
}
Step 2. Reorder Method in Controller
In our controller we will add a special function that would save all positions for all inputs.
app/Http/Controllers/Admin/CurrenciesController.php:
class CurrenciesController extends Controller
{
// ...
public function reorder(Request $request)
{
foreach($request->input('rows', []) as $row)
{
Currency::find($row['id'])->update([
'position' => $row['position']
]);
}
return response()->noContent();
}
}
What is this method called? In routes/web.php:
Route::post('currencies/reorder', 'CurrenciesController@reorder')->name('currencies.reorder');
Step 3. Blade and JavaScript: Hide Position and Reorder
In our QuickAdminPanel builder we have data tables in resources/views/admin/currencies/index.blade.phpso here is the JavaScript code for the data tables:
<table class=" table table-bordered table-striped table-hover datatable datatable-Currency">
...
</table>
@section('scripts')
@parent
<script>
$(function () {
let dtButtons = $.extend(true, [], $.fn.dataTable.defaults.buttons)
$.extend(true, $.fn.dataTable.defaults, {
order: [[ 2, 'asc' ]],
pageLength: 100,
columnDefs: [
...$.fn.dataTable.defaults.columnDefs,
{
visible: false,
searchable: false,
targets: 2
}
],
rowReorder: {
selector: 'tr td:not(:first-of-type,:last-of-type)',
dataSrc: '2'
},
});
let datatable = $('.datatable-Currency:not(.ajaxTable)').DataTable({ buttons: dtButtons })
datatable.on('row-reorder', function (e, details) {
if(details.length) {
let rows = [];
details.forEach(element => {
rows.push({
id: $(element.node).data('entry-id'),
position: element.newData
});
});
$.ajax({
headers: {'x-csrf-token': _token},
method: 'POST',
url: "{{ route('admin.currencies.reorder') }}",
data: { rows }
}).done(function () { location.reload() });
}
});
})
</script>
@endsection
In this case, we assume that position is column number 2 (which is the third column, numbers start at 0), so we hide it visually, but make it a source of reordering.
Step 3b. AJAX data tables
The code is a little different for the AJAX Datatables module with server-side rendering. Here is an example of a similar one resources/views/admin/countries/index.blade.php Since:
<table class=" table table-bordered table-striped table-hover ajaxTable datatable datatable-Country">
...
</table>
...
<script>
$(function () {
let dtButtons = $.extend(true, [], $.fn.dataTable.defaults.buttons)
let dtOverrideGlobals = {
buttons: dtButtons,
processing: true,
serverSide: true,
retrieve: true,
aaSorting: [],
ajax: "{{ route('admin.countries.index') }}",
columns: [
{ data: 'placeholder', name: 'placeholder' },
{ data: 'id', name: 'id' },
{ data: 'position', name: 'position', visible: false, searchable: false },
{ data: 'name', name: 'name' },
{ data: 'short_code', name: 'short_code' },
{ data: 'actions', name: '{{ trans('global.actions') }}' }
],
order: [[ 2, 'asc' ]],
pageLength: 100,
rowReorder: {
selector: 'tr td:not(:first-of-type,:last-of-type)',
dataSrc: 'position'
},
};
let datatable = $('.datatable-Country').DataTable(dtOverrideGlobals);
datatable.on('row-reorder', function (e, details) {
if(details.length) {
let rows = [];
details.forEach(element => {
rows.push({
id: datatable.row(element.node).data().id,
position: element.newData
});
});
$.ajax({
headers: {'x-csrf-token': _token},
method: 'POST',
url: "{{ route('admin.countries.reorder') }}",
data: { rows }
}).done(function () { datatable.ajax.reload() });
}
});
});
</script>
That’s it! The public repository is available here on Github.