AJAX Datatables: Move View/Edit/Delete Column from Right to Left Side
Founder of QuickAdminPanel
While generating the tables in QuickAdminPanel, our last column is the one with links to View/Edit/Delete record. One of our customers asked: what if you want to have that column as first one, in the very beginning? Tricky part is how to do that with AJAX Datatable module. Let’s take a look.
Step 1. Starting Point: Default AJAX Datatable Code
Here’s the default table:
To load it, we have code in a few different parts.
First, Blade file – resources/views/projects/index.blade.php:
Table itself – without data, cause it’s loaded with AJAX call later.
<table class=" table table-bordered table-striped table-hover ajaxTable datatable datatable-Project"> <thead> <tr> <th width="10"> </th> <th> {{ trans('cruds.project.fields.id') }} </th> <th> {{ trans('cruds.project.fields.name') }} </th> <th> {{ trans('cruds.project.fields.description') }} </th> <th> </th> </tr> </thead> </table>
And then JavaScript part to load Datatables:
@section('scripts') @parent <script> $(function () { let dtButtons = $.extend(true, [], $.fn.dataTable.defaults.buttons) let dtOverrideGlobals = { buttons: dtButtons, processing: true, serverSide: true, retrieve: true, aaSorting: [], ajax: "{{ route('admin.projects.index') }}", columns: [ {data: 'placeholder', name: 'placeholder'}, {data: 'id', name: 'id'}, {data: 'name', name: 'name'}, {data: 'description', name: 'description'}, {data: 'actions', name: '{{ trans('global.actions') }}'} ], order: [[1, 'desc']], pageLength: 100 } $('.datatable-Project').DataTable(dtOverrideGlobals) $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { $($.fn.dataTable.tables(true)).DataTable() .columns.adjust() }) }) </script> @endsection
Data comes from the Controller index() method, with help of jQuery Datatables Laravel package.
Here’s app/Http/Controllers/Admin/ProjectsController.php:
$query = Project::query()->select(sprintf('%s.*', (new Project)->table)); $table = Datatables::of($query); $table->addColumn('placeholder', ' '); $table->addColumn('actions', ' '); $table->editColumn('actions', function ($row) { $viewGate = 'project_show'; $editGate = 'project_edit'; $deleteGate = 'project_delete'; $crudRoutePart = 'projects'; return view('partials.datatablesActions', compact( 'viewGate', 'editGate', 'deleteGate', 'crudRoutePart', 'row' )); }); $table->editColumn('id', function ($row) { return $row->id ? $row->id : ""; }); $table->editColumn('name', function ($row) { return $row->name ? $row->name : ""; }); $table->editColumn('description', function ($row) { return $row->description ? $row->description : ""; }); $table->rawColumns(['actions', 'placeholder']); return $table->make(true);
It may look a bit complicated, but what is happening here is just getting the query from the database and overriding some logic for some columns, including actions column that we care about.
So, how to move it to the front?
Step 2. Changing Blade Columns Order
To change the order of the columns, it’s generally enough to move <th> elements as you wish, and then keep the same order in JavaScript columns array.
So, in changed resources/views/projects/index.blade.php we have this.
1. We move the empty th element from the last position to the second one. First column is reserved for checkboxes for mass-delete operation.
<table class=" table table-bordered table-striped table-hover ajaxTable datatable datatable-Project"> <thead> <tr> <th width="10"> </th> <th> </th> <th> {{ trans('cruds.project.fields.id') }} </th> <th> {{ trans('cruds.project.fields.name') }} </th> <th> {{ trans('cruds.project.fields.description') }} </th> </tr> </thead> </table>
2. We change the order in columns array of the same file:
ajax: "{{ route('admin.projects.index') }}", columns: [ {data: 'placeholder', name: 'placeholder'}, {data: 'actions', name: '{{ trans('global.actions') }}'}, {data: 'id', name: 'id'}, {data: 'name', name: 'name'}, {data: 'description', name: 'description'} ],
3. In the same file below, we need to change the default order, because by default it orders by Column 1 Desc:
order: [[1, 'desc']],
And now Column 1 is the “actions” one – columns are enumerated starting from 0.
So we need to change the order to this:
order: [[2, 'desc']],
And here’s the result:
As we wanted, the buttons are on the left side, right?
Not done yet, there’s one more thing we need to take care of.
Step 3. Make This New Column Not Searchable
Datatable will work now, but if we try to search on top-right, it will fail:
The reason is that it’s trying to search in “actions” column, and can’t find it in database. And that’s true, it’s our own custom column which is not corresponding to any database column.
There’s another file you should know, which contains main Datatables settings.
It’s resources/views/layouts/admin.blade.php, and it contains this JavaScript:
$.extend(true, $.fn.dataTable.defaults, { language: { url: languages['{{ app()->getLocale() }}'] }, columnDefs: [{ orderable: false, className: 'select-checkbox', targets: 0 }, { orderable: false, searchable: false, targets: -1 }], select: { style: 'multi+shift', selector: 'td:first-child' }, order: [], scrollX: true, pageLength: 100, dom: 'lBfrtip<"actions">', buttons: [ { extend: 'copy', className: 'btn-default', text: copyButtonTrans, exportOptions: { columns: ':visible' } }, // ... other buttons ] });
What we care about here is columnDefs parameter – it contains array of column settings that are applicable to all datatables.
In our case, by default column number 0 (targets: 0) is for checkboxes for multi-delete.
And then there’s targets: -1 which means the LAST column, which is reserved for View/Edit/Delete buttons, so it should be not orderable and not searchable.
So what we need to change here is to override that default setting in our own Projects CRUD’s JavaScript.
Here’s our updated resources/views/projects/index.blade.php:
columns: [ {data: 'placeholder', name: 'placeholder'}, {data: 'actions', name: '{{ trans('global.actions') }}', orderable: false, searchable: false }, {data: 'id', name: 'id'}, {data: 'name', name: 'name'}, {data: 'description', name: 'description', orderable: true, searchable: true } ],
And that’s it, we have the final result – search is working again!
For more information on AJAX Datatables module, read this article or watch this video.
Also, check out documentation of underlying Laravel package: Yajra Datatables.