Datatable Complete Example

Controller

 <?php
namespace App\Traits;
 
// To set $locale value of a model and translate all translatable attributes
trait AjaxResponse
{
    protected function success_response($data, $extra=null){
        $response = [
            'status' => 'success', 
            'data' => $data, 
            'extra' => $extra
        ];

        //header('Content-Type: application/json');
        //echo json_encode($response);
        //exit();
        return response()->json($response);
    }

    protected function fail_response($msg, $code=0){
        $response = [
            'status' => 'fail', 
            'code' => $code, 
            'message' => $msg
        ];

        //header('Content-Type: application/json');
        //echo json_encode($response);
        //exit();

        return response()->json($response);
    }

    protected function error_response($errors, $msg='網路錯誤'){
        $response = [
            'message' => $msg,
            'errors' => $errors
        ];

        return response()->json($response, 422);
    }

    protected function datatable_response($total, $filtered_total, $data=[], $draw=0){
        header('Content-Type: application/json');

        $out = array();
        $out['draw'] = $draw;
        $out['recordsTotal'] = $total;
        $out['recordsFiltered'] = $filtered_total;
        $out['data'] = $data;
     
        echo json_encode($out);
        exit();
    }
}

Model

<?php
namespace App\Models\Permission;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Config;
use Illuminate\Database\Eloquent\Model;

use Carbon\Carbon;

class RoleM extends Model{
    protected $table = 'roles';
    static $stable = 'roles';

    protected $primaryKey = 'id';
    public $timestamps = false;
    static $stimestamps = false;
    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';

    const DT_TOTAL = 1;
    const DT_FILTERED = 2;

    static function get_sorting($req){
        $columns = $req->input('columns');
        $order = $req->input('order');

        $sort_index = $order[0]['column'];
        $dir = $order[0]['dir'];
        $name = $columns[$sort_index]['data'];
        $sort = [
            $name => $dir
        ];

        return $sort;
    }

    static function items($options, $return_type=0){
        $result = DB::table(self::$stable);

        if($return_type == self::DT_TOTAL){
            return $result->count();
        }

        $keyword = val($options, 'keyword');
        if($keyword != false){
            $result = $result->where(function($query) use ($keyword){
                $find = '%' . $keyword . '%';
                $query->orWhere('name', 'like', $find);
                $query->orWhere('id', 'like', $find);
            });
        }

        if($return_type == self::DT_FILTERED){
            return $result->count();
        }

        if(val($options, 'sort') != false){
            $sorting = val($options, 'sort');
            foreach ($sorting as $key => $value) {
                $result = $result->orderBy($key, $value);
            }
        }else{
            $result = $result->orderBy('name', 'asc');
        }

        $result = $result->skip($options['start'])
            ->take($options['limit'])
            ->get();

        return $result;
    }

    static function datatable_data($data){
        foreach($data as $item){
            $item->action = self::item_action($item);
        }

        return $data;
    }

    static function item_action($item){
        $value = '<div class="dropdown">
            <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
                Select
                <span class="caret"></span>
            </button>
            <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">';

        $value .= '<li><a href="#" class="action edit" data-id="' . $item->id . '">Edit</a></li>';
        $value .= '<li><a href="#" class="action delete" data-id="' . $item->id . '">Delete</a></li>';
                    
        $value .= '</ul>
            </div>';

        return $value;
    }
}

Javascript (index.js)

$(document).ready(function(){
    dt_app.init();

    $('#new_item').on('click', function(e){
        var params = {
        }

        window.location.href = base_url + 'admin/' + controller + '/create';
    });
});

var dt_app = function(){
    var $c = null;
    var $t = null;
    var datatable = null;
    var extra_data = null;

    function init(){
        $c = $(".main-content");
        $t = $c.find('#dt_table');
        
        init_actions();
        init_dt();
    }

    function init_dt(){
        datatable = $t.DataTable({
            "searching": true,
            "info": true,
            "lengthChange": true,
            "paging": true,
            'serverSide': true, 
            'processing': true, 
            "order": [[ 0, "asc" ]], 
            "ajax": {
                'url': base_url + 'admin/' + controller + '/all',
                'data': function(d){
                    //d.pid = pid;
                }, 
                //Get complete json data
                "dataSrc": function ( json ) {
                    //console.log(json);
                    extra_data = json.extra;
                    console.log(extra_data);
                    return json.data;
                }
            },
            'columns': [
                {
                    'data': 'id', 
                    'title': 'ID'
                },
                {
                    'data': 'name', 
                    'title': 'Name'
                },
                {
                    'data': 'created_at', 
                    'title': 'Created Time'
                },
                {
                    'data': 'action', 
                    'title': 'Action'
                },
            ],  
            "drawCallback": function( settings ) {
                var api = this.api();
                //wrap.loaded(settings);
                loaded(settings);
            }, 
            'initComplete': function(settings, json){
                //loaded(settings);
            }
        });
    }

    function loaded(oSettings){

    }

    function refresh(){
        if(datatable != null){
            datatable.destroy();
        }
        
        init_dt();
    }

    function init_actions(){
        $t.delegate('tbody tr .action.edit', 'click', function(e){
            e.preventDefault();
            var $this = $(this);
            var id = $this.data('id');
            var params = {
                id: id
            }

            window.location.href = base_url + 'admin/' + controller + '/edit?' + $.param(params);
        });

        $t.delegate('tbody tr .action.delete', 'click', function(e){
            e.preventDefault();
            var $this = $(this);
            var id = $this.data('id');

            if(confirm('Are you sure to delete this item?') == true){
                delete_item(id);
            }
        });
    }

    function delete_item(id){
        var params = {
            id: id
        }
        //console.log(params);
        //return;

        $.ajax({
            type: 'post',
            url: base_url + 'admin/' + controller + '/delete',
            data: params,
            dataType: 'json',
            success: function(data){
                if(typeof data.status == 'undefined'){
                    alert(data);
                }else if(data.status == 'fail'){
                    alert(data.message);
                }else{
                    alert('Item is deleted.');
                    refresh();
                }
            },
            error: function(data){
                console.log(data);
                var errors = data.responseJSON;
                show_response_error(errors);
            }
        });
    }

    return {
        init: init, 
        refresh: refresh
    }
}();

AjaxResponse Trait

<?php
namespace App\Traits;
 
// To set $locale value of a model and translate all translatable attributes
trait AjaxResponse
{
    protected function success_response($data, $extra=null){
        $response = [
            'status' => 'success', 
            'data' => $data, 
            'extra' => $extra
        ];

        //header('Content-Type: application/json');
        //echo json_encode($response);
        //exit();
        return response()->json($response);
    }

    protected function fail_response($msg, $code=0){
        $response = [
            'status' => 'fail', 
            'code' => $code, 
            'message' => $msg
        ];

        //header('Content-Type: application/json');
        //echo json_encode($response);
        //exit();

        return response()->json($response);
    }

    protected function error_response($errors, $msg='網路錯誤'){
        $response = [
            'message' => $msg,
            'errors' => $errors
        ];

        return response()->json($response, 422);
    }

    protected function datatable_response($total, $filtered_total, $data=[], $draw=0, $extra=null){
        header('Content-Type: application/json');

        $out = array();
        $out['draw'] = $draw;
        $out['recordsTotal'] = $total;
        $out['recordsFiltered'] = $filtered_total;
        $out['data'] = $data;
        $out['extra'] = $extra;
     
        echo json_encode($out);
        exit();
    }
}