IgnitedDatatables / Ignited-Datatables

Ignited Datatables is a wrapper class/library based on the native Datatables server-side implementation by Allan Jardine found at http://datatables.net/examples/data_sources/server_side.html for CodeIgniter
285 stars 335 forks source link

Use this version instead #132

Open wrabit opened 6 years ago

wrabit commented 6 years ago

https://github.com/chland/Ignited-Datatables

Based on this class. It is faster than this library thanks to some optimisations. (10,000 serverside rows from ~2.5 seconds to ~1.2).

virtualgadjo commented 6 years ago

you're right, works like a charm and fast only issue for me, i can't figure out how to have it work with column search/filtering (general sSearch works fine) it displays the usual processing short "alert" but nothing changes have a good day

wrabit commented 6 years ago

The library (Same with this) is hardcoded to process POST requests, but datatables will by default use GET. So make sure in your DataTables init you sent "POST" like:

                .....
            ajax: {
                url: url,
                type: "POST"
            },

You could also check your XHR request log in chrome dev tools and providing you are showing php errors it might reveal something else.

virtualgadjo commented 6 years ago

hi, that's what i do but the thing is a little funnier than this... using the latest release of datatables, in order to have my inpus work i use this $( ctable.table().container() ).on( 'keyup', 'tfoot input', function () { ctable .column( $(this).data('index') ) .search( this.value ) .draw()(); }); funny enough, if i comment or retrieve the column() line it "works" but every input works like the main search, searching in all columns data i've checked if $(this).data('index') was correct and yes, it returns the correct column index

a close look inside the library later i've seen it deals with a columns value in the get_filtering function but not a single column index one so i've tried naming my column data into columns, thinking it could work as a single value array, nope, still have to dig a little big deeper i'm afraid :)

of course, ajax, so i've tried putting this inside the ajax complete function but no more success :) (when the use of tooltips works fine this way)

unfortunately, chrome console doesn't find anything to say :)

i was the way i used the original library with CI 2 (i still have some tools working fine like so) too bad it doesn't work with CI3 but this fork is really fast and works really well except when it comes to column ajax filtering, i'll continue to try and understand why... or more precisely, how i could have it deal with that single column index...

have a nice day

wrabit commented 6 years ago

Hmm I think you should try and keep to defining searchable columns within the init of the plugin like so and fix the real issue.

Ensure you have XHR requests logging turned on (right click console window). Turn logging threshold for errors and check application/logs for other errors to do with the query. Paste it all up here if you want me to take a look (including Controller side query for the data.

        $('#tickets-datatable').DataTable( {
            processing: true,
            serverSide: true,
            ajax: {
                url: "url",
                type: "POST"
            },
            columns: [
                {
                    data: 'ticket_created',
                    searchable: false
                },
                {
                    data: 'ticket_status',
                    searchable: false
                },
                {
                    data: 'ticket_title',
                },
                {
                    data: 'staff_first_name',
                },
                {
                    data: 'reply_count',
                    searchable: false,
                    orderable: false
                },
                {
                    data: 'ticket_last_reply_at',
                    searchable: false
                }
            ]
        });

    <table class="table" id="tickets-datatable" width="100%">
        <tr>
            <thead>
                <th>Date</th>
                <th>Status</th>
                <th>Ticket</th>
                <th>Assigned</th>
                <th>Replies</th>
                <th>Last Reply</th>
            </thead>
        </tr>
    </table>
virtualgadjo commented 6 years ago

just a word to say, of course it's draw() not .draw()(); :)

virtualgadjo commented 6 years ago

just seen your message, i'll try this instead of my columnDefs declaration, beeing back soon :)

virtualgadjo commented 6 years ago

nope, doesn't work... you know, in order to have search inputs in the table footer with the latest releases of datatables you have to use this method (full datatable call

$('#users_list tfoot th').each( function (i) {

    if ( i != 0 && i != 5 && i != 6 )
    {
        var title = $('#users_list thead th').eq( $(this).index() ).text();
        $(this).html( '<input type="text" placeholder="'+title+'" data-index="'+i+'" />' );
    }
});

var ctable = $('#users_list').DataTable({
    "processing": true,
    "serverSide": true,
    "lengthMenu": [[10, 20, 50, 100, -1], [10, 20, 50, 100, "tout"]],
    "pageLength": 20,

    "ajax": {
        "url" : "/mpprivate/users/users_tab",
        "type": "post",
        'complete': function(){
            $('.toollink').tooltip();
        }
    },

    "columnDefs": [
    { "name": "prenom",    "targets": 1 },
    { "name": "nom",       "targets": 2 },
    { "name": "cp_ville",  "targets": 3 },
    { "name": "pays",      "targets": 4 },
    { "name": "valide",    "targets": 5 },
    { "visible": false,    "targets": 0 },
    { "searchable": false, "targets": [5,6] },
    { "orderable": false,  "targets": [5,6] }
    ],

    "order": [[ 2, "asc" ], [ 1, "asc" ]],
    "language": datatabfr
});

$( ctable.table().container() ).on( 'keyup', 'tfoot input', function () {
    ctable
    .column( $(this).data('index') )
    .search( this.value )
    .draw();
});

and, just to be as complete as possible

the ajax url does something really simple

public function users_tab()
{
    $this->datatables
    ->select('mp2018_user.id, prenom, nom, cp_ville, pays, valide')
    ->from('mp2018_user')
    ->add_column('voir', '<a href="/contacts/un_contact?idcontact=$1" title="voir / modifier" class="toollink"><i class="far fa-eye fa-lg"></i></a>', 'id');

    $data['result'] = $this->datatables->generate();
    $this->load->view('raw_ajax', $data);
}

anyway, thanks a lot for your help and interest in this funny issue :)

virtualgadjo commented 6 years ago

forgot to add, i've a lot of datatables with this exact syntax working like a charm in CI 2 with the original Ignited-Datatables library, what make me think the issue is probably in the library, maybe the todo : sRangeSeparator in the get_filtering function :)

virtualgadjo commented 6 years ago

hi again, found out and, as usual, the problem was behind the bench and the machine not in the library... the right call is (below the full datatables statement)

$( ctable.table().container() ).on( 'keyup', 'tfoot input', function () {
    ctable.column.search( this.value ).draw();
});

instead of the one i have been using for quite a long time... and, curiously works fine when not server side

well, back again to say i've been a little too enthusiatic, it keeps having problem, i keep digging... have a nice day

briansulzen commented 5 years ago

@virtualgadjo Figured something out with this. It could be cleaned up a lot, but this will allow you to use searchCols server side to define a column search alone or in combination with the default datatables search. I pass the $page_filter var via PHP to filter by order status. Hope this helps someone.

In your javascript call: ` $(document).ready(function() {

    $('#orders').dataTable( {
        dom: '<fp<t>ip>',
        processing: false,
        stateSave: false,
        serverSide: true,
        ajax: {
            url: '<?php echo base_url(); ?>index.php?/orders/list_orders',
            type: 'POST'
        },
        searchCols: [
            {"sSearch": "<?php echo $page_filter; ?>"},null,null,null,null,null,null
        ],
        lengthChange: false,
        pagingType: 'full_numbers',
        displayStart: 0,
        pageLength: 100,
        ordering: true,
        order: [[5,"desc"]] ,
        language: {
            'search': 'Search all Columns: '
        },
        // style past due amount cell for account that are in the red.
        // Also disable search on the past amount due column
        columnDefs: [
            {
                targets: 7,
                render: $.fn.dataTable.render.number( ',', '.', 2),
                createdCell: function (td, cellData, rowData, row, col) {
                    if (cellData.substring(0,1) !== '-' && cellData.substring(0,1) != 0){
                        $(td).css('color', 'red');
                    }
                },
                searchable: false
            },
            {
                // Display the date in more readable format
                targets: 5,
                render: function ( data, type, row ) {
                    var jDate = new Date(row[5]);
                    jDate = jDate.toLocaleString('en-US');
                    return jDate;
                }
            },
            {
                targets: [6,8],
                className: "hide"
            }
        ],
        // Style Do Not Ship Customer's row color background
        createdRow: function(tr,data,dataIndex) {
            if(data[6] == '6') {
                $(tr).addClass('error');
            }

            if(data[8] === "Amazon Prime") {
                $(tr).find('td:eq(3)').css({'background-image':'url("template/images/prime_small.png")','background-repeat':'no-repeat', 'background-position':'140px'});
            }
        }

    });
    $('#orders tbody').on('click','tr', function() {
        var order_id = $('td',this).eq(1).text();
         window.location = '<?php echo base_url(); ?>index.php?/orders/edit_order_entry/'+order_id;
    } );

});

`

Amended Datatables.php get_filtering() method:

` private function get_filtering() {

    $mColArray  = $this->ci->input->post('columns');

    $sWhere     = '';
    $colWhere = '';
    $colSearch = '';
    $search     = $this->ci->input->post('search');
    $sSearch    = $this->ci->db->escape_like_str(trim($search['value']));
    $columns    = array_values(array_diff($this->columns, $this->unset_columns));

    if ($sSearch != '') {
        for ($i = 0; $i < count($mColArray); $i++) {

            if ($mColArray[$i]['searchable'] == 'true' && !array_key_exists($mColArray[$i]['data'], $this->add_columns)) {

                if ($this->check_cType()) {
                    $sWhere .= $this->select[$mColArray[$i]['data']]." LIKE '%".$sSearch."%' OR ";

                } else {
                    $sWhere .= $this->select[$this->columns[$i]]." LIKE '%".$sSearch."%' OR ";

                }
            }
        }
    }

    for ($i = 0; $i < count($mColArray); $i++) {
        $colSearch = $this->ci->db->escape_like_str(trim($mColArray[$i]['search']['value']));

        if ($mColArray[$i]['searchable'] == 'true' && !array_key_exists($mColArray[$i]['data'], $this->add_columns) && $mColArray[$i]['search']['value'] != '') {
             $colWhere .= " AND ".$this->select[$this->columns[$i]]." LIKE '%".$colSearch."%'";

        }

    }

    if ($sWhere != '' && $colWhere != '') {
        $sWhere = substr_replace($sWhere, '', -3);
        $this->ci->db->where('('.$sWhere.') '.$colWhere);

    }
    else if ($sWhere != '') {
        $sWhere = substr_replace($sWhere, '', -3);
        $this->ci->db->where('('.$sWhere.')');

    }
    else if ($colWhere != '') {
        $colWhere = substr($colWhere,4);
        $this->ci->db->where($colWhere);

    }

    // TODO : sRangeSeparator

    foreach ($this->filter as $val) {
        $this->ci->db->where($val['key'], $val['value'], $val['escape']);
    }

}

`

zieru commented 5 years ago

hello I'm sorry

I'm using this version but I can't implement #129 this one,