Datatable Server Side Processing (CI)

Javascript:

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

    function init(){
        $t = $('#datatable');
        
        init_actions();
        init_dt();
    }

    function init_dt(){
        datatable = $t.DataTable({
            "searching": true,
            "info": true,
            "lengthChange": true,
            "paging": true,
            'serverSide': true, 
            'processing': true, 
            "order": [[ 0, "desc" ]], 
            "ajax": {
                'url': base_url + 'admin/receipt/ajax_all',
                'data': function(d){
                    //d.selected = cat_tree_app.selected_id();
                }
            },
            "columnDefs": [
                {
                    "targets": [ 3, 8 ],
                    "visible": true,
                    "searchable": true
                }
            ], 
            "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 td .switch .lever', 'click', function(e){
            var $this = $(this);
            var $switch = $this.closest('.switch');
            //console.log($switch.length);

            var params = {
                pid: $switch.data('id'), 
                prop: $switch.data('field')
            }
            
            $.ajax({
                type: 'post',
                url: base_url + 'admin/product/ajax/prop',
                data: params,
                dataType: 'json',
                success: function(data){
                    if(typeof data.status == 'undefined'){
                        alert(data);
                    }else if(data.status == 'fail'){
                        alert(data.message);
                    }else{
                        //console.log(data);
                    }
                },
                error: function(data){
                    var errors = data.responseJSON;
                    show_response_error(errors);
                }
            });
        });

        $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/product/edit?' + $.param(params);
        });

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

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

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

            var url = site_url + '/products/preview/' + id; 
            window.open(url);
        });

        $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 product?') == true){
                delete_item(id);
            }
        });

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

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

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

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

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

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

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

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

Server:

Column config

$config['receipt_table_fields'] = array(
	'id' => array('流水號', false, false),
	'order_no' => array('經銷商訂單編號', true, true),
	'rid' => array('收據編號', true, true),
	'airport' => array('機場', true, true),
	'products' => array('商品', false, true),
	'amount' => array('金額', false, true),
	'discount' => array('折扣', false, true),
	'shipping' => array('運費', false, true),
	'final_amount' => array('總金額', true, true),
	'status' => array('狀態', true, true),
	'created_at' => array('建立時間', true, 'string'),
	'action' => array('動作', true, 'string')
);

 

Controller

	public function ajax_all(){
		$draw = $this->input->get('draw');
		$start = $this->input->get('start');
		$length = $this->input->get('length');
		$search = $this->input->get('search');
		$keyword = $search['value'];

		$order = $this->input->get('order');
		$sorting = $this->receipt_m->datatable_sorting($order);
		//logg($sort);
		
		$options = [
            'start' => $start, 
            'limit' => $length, 
            'sort' => $sorting, 
            'keyword' => $keyword, 
        ];
        $total = $this->receipt_m->items($options, Receipt_m::DT_TOTAL);
        $filtered_total = $this->receipt_m->items($options, Receipt_m::DT_FILTERED);
        $data = $this->receipt_m->items($options);

        $data = $this->receipt_m->datatable_data($data);
        //logg($data);

        $this->datatable_response($total, $filtered_total, $data, $draw);
	}

Ajax Response

    public function datatable_response($total, $filtered_total, $data=[], $draw=0){
        $out = array();
        $out['draw'] = $draw;
        $out['recordsTotal'] = $total;
        $out['recordsFiltered'] = $filtered_total;
        $out['data'] = $data;

        if($this->is_laravel == false){
            header('Content-Type: application/json');
            echo json_encode($out);
            exit();
        }else{
            return response()->json($out);
        }
    }

Model

    public function datatable_sorting($order){
        $columns = $this->config->item($this->table_config);

        $sort = array();
        foreach($order as $key => $item){
            $col_index = $item['column'];
            $dir = $item['dir'];

            $column = null;
            $column_key = null;
            $i = 0;
            foreach ($columns as $key => $item) {
                if($i == $col_index){
                    $column = $item;
                    $column_key = $key;
                    break;
                }
                $i++;
            }

            $sort[$column_key] = $dir;
        }

        return $sort;
    }

    public function items($options, $return_type=0){
        //$query = $this->db->get($this->table);
        //return $query->result();
        if($return_type == self::DT_TOTAL){
            return $this->db->count_all($this->table);
        }

        $keyword = val($options, 'keyword');
        if($keyword != false){
            $find = '%' . $keyword . '%';
            $this->db->where("(order_no like '" . $find . "' or rid like '" . $find . "')");
        }

        if($return_type == self::DT_FILTERED){
            return $this->db->count_all_results($this->table);
        }

        if(val($options, 'sort') != false){
            $sorting = val($options, 'sort');
            foreach ($sorting as $key => $value) {
                $this->db->order_by($key, $value);
            }
        }else{
            $result = $result->orderBy(self::CREATED_AT, 'desc');
        }

        $this->db->limit($options['limit'], $options['start']);
        $query = $this->db->get($this->table);
        return $query->result();
    }

    public function datatable_data($data){
        $fields = $this->config->item($this->table_config);

        $new_data = array();
        foreach($data as $item){
            $item_values = [];

            foreach ($fields as $key => $field) {
                $value = val($item, $key);

                if($key == 'art_no'){
                    $value = implode(', ', self::models_art_no($item->id));
                }

                if($key == 'action'){
                    $value = $this->item_action($item, $field);
                }

                $item_values[] = $value;
            }

            array_push($new_data, $item_values);
        }

        return $new_data;
    }

    public function item_action($item, $field){
        $action = '<div class="btn-group">' .
                '<a href="#" data-toggle="dropdown" class="btn btn-primary dropdown-toggle"><i class="icon-cog"></i> <span class="caret"></span></a>' .
                '<ul class="dropdown-menu">';

        $action .= '<li><a href="#" class="edit">檢視</a></li>';

        $action .= '</ul></div>';

        return $action;
    }