Create Drag and Droppable Datatables Using jQuery UI Sortable in Laravel


Datatables is one of the most popular jQuery javascript library used to enhance the functionalities of HTML table and jQuery UI is a curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library. In this tutorial, I will show how to use jQuery UI Sortable along with Datatables to add drag and drop functionality to it. We will be using laravel as the backend to save the new position in the database. Besides Datatables and jQuery UI don't forget to add jQuery as both plugins depend on it and we also will be using jQuery $.ajax function for Ajax  Functionality. I also try to make this tutorial very basic so that everyone can easily follow. All you need to know is basic of jQuery and Laravel.

Let's Start Coding

First, let's make a DemoTask Table migration and Model by running the following command.

php artisan make:model DemoTask -m

Now In the Migration file,

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateDemoTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('demo_tasks', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->integer('order')->unsigned()->default(0);
            $table->integer('status')->unsigned()->default(0);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('demo_tasks');
    }
}

 

I used unsigned because the value of order and status fields will not be less than zero. So it helps us to save some space. The Order field is used to determine the order of our task and status field will have a boolean value which determines whether the task is completed or not.

Now let's migrate the table.

 php artisan migrate 

The complete code in DemoTask Model is given below.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class DemoTask extends Model
{
     /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id', 'title','order', 'status',
    ];
}

 

The codes for the model is very basic. It has fillable fields predefined since we use mass assignments in our controller function.

Now let's makes our required routes in routes/web.php 

Route::get('demos/sortabledatatable','DemoController@showDatatable');
Route::post('demos/sortabledatatable','DemoController@updateOrder');

 

Although it is better to use PUT Request for update functionality, I am using plain old POST Request for simplicity. But feel free to use PUT or PATCH if you know how to use it.

Now Let's create our DemoController by running the following command.

php artisan make:controller DemoController

The complete code for DemoController is given below.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\DemoTask;

class DemoController extends Controller
{
    public function showDatatable()
    {
        $tasks = DemoTask::orderBy('order','ASC')->select('id','title','status','created_at')->get();

        return view('demos.sortabledatatable',compact('tasks'));
    }

    public function updateOrder(Request $request)
    {
        $tasks = DemoTask::all();

        foreach ($tasks as $task) {
            $task->timestamps = false; // To disable update_at field updation
            $id = $task->id;

            foreach ($request->order as $order) {
                if ($order['id'] == $id) {
                    $task->update(['order' => $order['position']]);
                }
            }
        }
        
        return response('Update Successfully.', 200);
    }

}

 

The showDatatable function is used to display the view page. We are fetching tasks in the ascending order based on 'order' field. The updateOrder function is used to update the order of tasks. This function is called by view page as an ajax post call. The post request will have an associative array of task id's and new task orders. We just update the order of the given task that matches the task id inside the nested loop. 

Now let's see the complete code for our View page - demos/sortabledatatable.blade.php file

@extends('main')

@section('title','Drag and Drop Datatables Using jQuery UI Sortable - Demo')

@section('stylesheets')

    <!-- Datatables Js-->
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.12/datatables.min.css"/>
    
@stop

@section('content')

<!-- search box container starts  -->
    <div class="search">
        <h3 class="text-center title-color">Drag and Drop Datatables Using jQuery UI Sortable - Demo </h3>
        <p>&nbsp;</p>
        <div class="row">
            <div class="col-lg-10 col-lg-offset-1">
                <table id="table" class="table table-bordered">
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Title</th>
                      <th>Status</th>
                      <th>Created At</th>
                    </tr>
                  </thead>
                  <tbody id="tablecontents">
                    @foreach($tasks as $task)
                    <tr class="row1" data-id="{{ $task->id }}">
                      <td>
                        <div style="color:rgb(124,77,255); padding-left: 10px; float: left; font-size: 20px; cursor: pointer;" title="change display order">
                        <i class="fa fa-ellipsis-v"></i>
                        <i class="fa fa-ellipsis-v"></i>
                        </div>
                      </td>
                      <td>{{ $task->title }}</td>
                      <td>{{ ($task->status == 1)? "Completed" : "Not Completed" }}</td>
                      <td>{{ date('d-m-Y h:m:s',strtotime($task->created_at)) }}</td>
                    </tr>
                    @endforeach
                  </tbody>                  
                </table>
            </div>
        </div> 
        <hr>
        <h5>Drag and Drop the table rows and <button class="btn btn-default" onclick="window.location.reload()"><b>REFRESH</b></button> the page to check the Demo. For the complete tutorial of how to make this demo app visit the following <a href="#">Link</a>.</h5> 
    </div>  

     
@stop

@section('scripts')

  <!-- jQuery UI -->
  <script type="text/javascript" src="//code.jquery.com/ui/1.12.1/jquery-ui.js" ></script>
 
  <!-- Datatables Js-->
  <script type="text/javascript" src="//cdn.datatables.net/v/dt/dt-1.10.12/datatables.min.js"></script>

  <script type="text/javascript">
  $(function () {
    $("#table").DataTable();

    $( "#tablecontents" ).sortable({
      items: "tr",
      cursor: 'move',
      opacity: 0.6,
      update: function() {
          sendOrderToServer();
      }
    });

    function sendOrderToServer() {

      var order = [];
      $('tr.row1').each(function(index,element) {
        order.push({
          id: $(this).attr('data-id'),
          position: index+1
        });
      });

      $.ajax({
        type: "POST", 
        dataType: "json", 
        url: "{{ url('demos/sortabledatatable') }}",
        data: {
          order:order,
          _token: '{{csrf_token()}}'
        },
        success: function(response) {
            if (response.status == "success") {
              console.log(response);
            } else {
              console.log(response);
            }
        }
      });

    }
  });

</script>

@stop

 

I am skipping the layout details as it will vary from project to project. Also, Please Note don't forget to include jQuery when you try this demo. I included both jQuery and Bootstrap in my layouts file. The HTML part of this view page is self-explanatory. All I do is just create a Bootstrap HTML table. 

Now let's explain Js Part.

First, you need to initialize the Datatables by calling DataTable() method. Now to add drag and drop functionality to tables content's we need to call sortable() method of jQuery UI. In that method parameter, we specify which function should be called when an update occurs. We will call the sendOrderToServer function when someone changes the order of table row. To increase the efficiency and speed I am storing the position and id in an associative array first by calling javascript array push method, Thus we only need one ajax request rather than multiple ajax request based on the number of rows which is a very bad idea. After making our associative array all you need to do is just call jquery $.ajax method. Don't forget to specify dataType as json as we are passing JSON format to the server.

The output image of above program is given below.

 Drag and Drop Datatables Using jQuery UI Sortable - Demo

The Demo

You can demo the above application by visiting following link.

https://shareurcodes.com/demos/sortabledatatable

If anybody has any suggestions or doubts or need any help comment below and I try will respond to every one of you as early as possible.


Web development
5th Jan 2018 07:29:02 PM
PHP Laravel Javascript jQuery Ajax
36971

ShareurCodes

ShareurCodes is a code sharing site for programmers to learn, share their knowledge with younger generation.