Position Re-Ordering with Drag/Drop – Quick Admin Panel


One of the features requested in our QuickAdminPanel, was drag’n’drop re-ordering of the entries in Datatables. For now, we decided to create a quick demo-project which would show you how to add this functionality.


Here’s the result of what we’ll be creating – 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/Currency.php model and want to add a new currency, here’s 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 the positions for all entries.

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();
    }
}

How do we call that method? In routes/web.php:


Route::post('currencies/reorder', 'CurrenciesController@reorder')->name('currencies.reorder');

Step 3. Blade & JavaScript: Hide Position and Reorder

In our QuickAdminPanel generator, we have datatables in resources/views/admin/currencies/index.blade.php, so here’s the JavaScript code for the datatables:


<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 third column, numbers start from 0), so we hide it visually, but make it a source of reordering.


Step 3b. AJAX Datatables

The code is a little bit different for AJAX Datatables module with server-side rendering. Here’s an example from a similar the same resources/views/admin/countries/index.blade.php from:


<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! Public repository is available here on Github.



Cloud Software

Berita Olahraga

Lowongan Kerja

Berita Terkini

Berita Terbaru

Berita Teknologi

Seputar Teknologi

Berita Politik

Resep Masakan

Pendidikan
Berita Olahraga
Berita Olahraga

News

Berita Terkini

Review Film

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *