DataTable: การค้นหาชั้นสูง

Byphunsanit

DataTable: การค้นหาชั้นสูง

เราสามารถเพิ่มเงื่อนไขให้ DataTables ใช้ในการค้นหาได้ โดยส่วนที่เปลี่ยนไปจากเดิมคือใช้ “beforeSend” ในการรวมข้อมูลจาก form (formA) และเขียน validation ง่ายๆ โดยบังคับว่าถ้า advanceSearch ถูกติ๊กอยู่จะต้องเลือก geo_id ด้วย ( จริง ๆ คือ ถึงไม่ติ๊ก advanceSearch ก็ใช้ geo_id search ได้เหมือนกัน )
jQuery.DataTables/data.json.external.search.html

<!doctype html>
<html>
 
<head>
    <meta charset="utf-8">
    <meta name="author" content="Pitt Phunsanit">
    <title>DataTables: external.search</title>
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">
    <link href="../vendor/datatables/datatables/media/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
</head>
 
<body>
    <form action="DataTables.json.php" class="form-inline" id="formA" method="post">
        <div class="form-group">
            <input name="advanceSearch" type="checkbox">
            <label for="advanceSearch">advance Search</label>
        </div>
        <div class="form-group">
            <label for="geo_id">ภูมิภาค:</label>
            <select class="form-control" name="geo_id">
               <option selected="selected" value="">--- Select ---</option>
               <option value="1">ภาคเหนือ</option>
               <option value="2">ภาคกลาง</option>
               <option value="3">ภาคตะวันออกเฉียงเหนือ</option>
               <option value="4">ภาคตะวันตก</option>
               <option value="5">ภาคตะวันออก</option>
               <option value="6">ภาคใต้</option>
            </select>
        </div>
        <button type="submit" class="btn btn-default">Search</button>
    </form>
    <table class="table table-bordered table-hover table-striped" id="tableA" width="100%"></table>
    <script src="../vendor/components/jquery/jquery.min.js"></script>
    <script src="../vendor/datatables/datatables/media/js/jquery.dataTables.min.js"></script>
    <script src="../vendor/datatables/datatables/media/js/dataTables.bootstrap.min.js"></script>
    <script src="data.json.external.search.js"></script>
</body>
 
</html>

jQuery.DataTables/data.json.external.search.js
$(function() {
 
    formA = $('#formA');
    tableA = $('#tableA');
 
    datatable = tableA.DataTable({
        "ajax": {
            "beforeSend": function(jqXHR, settings) {
                /* add value form from to DataTable params */
                settings.data = formA.serialize() + '&' + settings.data;
 
                /* validation */
                var params = new URLSearchParams(settings.data);
 
                /* user must selected region if enable advance search */
                if (params.get('advanceSearch') == 'on' && params.get('geo_id') == '') {
                    jqXHR.abort();
                    alert('กรุณาเลือกภูมิภาค');
                    return false;
                }
 
                return true;
            },
            "dataSrc": function(json) {
                alert('data back ' + json.data.length + ' items');
 
                return json.data;
            },
            "method": "POST",
            "url": "data.json.php",
        },
        "columns": [{
                "orderable": false,
                "render": function(data, type, row, meta) {
                    return parseInt(meta.row) + parseInt(meta.settings._iDisplayStart) + 1;
                },
                "title": 'No.',
                "width": "10px",
            },
            {
                "orderable": false,
                "render": function(data, type, row, meta) {
                    return '<input type="checkbox" value="' + row.DISTRICT_CODE + '">';
                },
                "title": '<input class="checkAll" type="checkbox">',
                "width": "10px",
            },
            {
                "orderable": false,
                "render": function(data, type, row, meta) {
                    if (row.enable == '1') {
                        return '<span class="glyphicon glyphicon-ok"></span>';
                    } else {
                        return '<span class="glyphicon glyphicon-remove"></span>';
                    }
                },
                "title": "Enable",
                "width": "10px",
            }, {
                "data": "DISTRICT_CODE",
                "title": "District Code",
                "width": "90px",
            }, {
                "data": "DISTRICT_NAME",
                "title": "District Name",
            }, {
                "data": "PROVINCE_NAME",
                "title": "Province Name",
            }
        ],
        /* default sort */
        "order": [
            [3, "asc"],
            [4, "asc"],
        ],
        "processing": true,
        "serverSide": true,
        "stateSave": true,
    });
 
    $('.checkAll', tableA).click(function() {
        $('input:checkbox', tableA).not(this).prop('checked', this.checked);
    });
 
    formA.submit(function(event) {
        event.preventDefault();
 
        datatable.ajax.reload();
    });
 
});
  • ข้อมูลจากฟอร์ม
    id="formA"
    
    จะถูกรวมกับ data ที่ DataTables สร้างขึ้นมาเองโดย
    beforeSend
    "beforeSend": function(jqXHR, settings) {
        settings.data = formA.serialize() + '&' + settings.data;
    },
    
  • สามารถทำ validation data ก่อนส่งข้อมูลออกไป ถ้าต้องการหยุดการทำงาน ก็ให้ใช้
    "beforeSend": function(jqXHR, settings) {
        jqXHR.abort();
    },
    

    ไม่ให้ส่งข้อมูลกลับไป server อาจจะดัดแปลงให้ datatable ไม่ขอข้อมูลจาก server กรณีที่ไม่มีการเลือกตัว filter ก็ได้เช่นกัน
  • หลังได้ข้อมูลกลับมายังสามารถใช้
    dataSrc / success
    "dataSrc": function(json) {
        alert('data back ' + json.data.length + ' items');
     
        return json.data;
    },
    

    แก้ไขข้อมูลก่อนแสดงผลได้ แต่ไม่ใช่ “success” เหมือนใน jQuery ajax ตามปกตินะครับ เพราะจะทำให้ DataTables มันทำงานผิดปกติได้เลย
  • ถ้าต้องการให้ DataTables ดึงข้อมูลใหม่ให้ใช้รูปแบบ

    datatable.ajax.reload();
    
  • ถ้าต้องการให้ DataTable ดึงข้อมูลใหม่ให้ใช้รูปแบบ
    refresh datatable
    
    datatable.ajax.reload();
    
    
    jQuery.DataTables/data.json.php
    <?php
    /* https://datatables.net/manual/server-side */
     
    $output = [
        'data' => [],
        'debug' => [
            'length' => $_REQUEST['length'],
            'post' => $_REQUEST,
            'sqlCount' => '',
            'sqlResult' => '',
            'start' => $_REQUEST['start'],
        ],
        'draw' => $_REQUEST['draw'],
        'recordsFiltered' => $_REQUEST['length'],
        'recordsTotal' => 0,
    ];
     
    $dns = new PDO('mysql:host=localhost;dbname=snippets', 'root', '', [
        //PDO::ATTR_EMULATE_PREPARES => false,
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
    ]);
     
    $condition = [];
    $from = ' FROM district AS d LEFT JOIN province AS p ON d.PROVINCE_ID = p.PROVINCE_ID';
    $parameters = [];
    $where = '';
     
    if (isset($_REQUEST['filters']) || isset($_REQUEST['search']['value'])) {
     
        if (isset($_REQUEST['search']['value'])) {
            if ($_REQUEST['search']['value'] != '') {
     
                $parameter = ':d_DISTRICT_NAME';
     
                $parameters[$parameter] = '%' . $_REQUEST['search']['value'] . '%';
                array_push($condition, 'd.DISTRICT_NAME LIKE ' . $parameter);
            }
        }
     
        if (isset($_REQUEST['filters'])) {
            foreach ($_REQUEST['filters'] as $tableAlias => $filter) {
                foreach ($filter as $field => $value) {
                    if ($value != '') {
                        $parameter = ':' . $tableAlias . '_' . $field;
     
                        $parameters[$parameter] = '%' . $value . '%';
                        array_push($condition, $tableAlias . '.' . $field . ' LIKE ' . $parameter);
                    }
                }
            }
        }
     
    }
     
    if (isset($_REQUEST['geo_id']) && $_REQUEST['geo_id'] != '') {
        $parameter = ':d_geo_id';
     
        $parameters[$parameter] = $_REQUEST['geo_id'];
        array_push($condition, 'd.GEO_ID = ' . $parameter);
    }
     
    if (count($parameters)) {
        $where = ' WHERE ' . implode("\n\t AND ", $condition);
    }
     
    if (isset($_REQUEST['order']) && isset($_REQUEST['order'][0])) {
        $columns = [
            0 => 'DISTRICT_NAME',
            3 => 'DISTRICT_CODE',
            4 => 'DISTRICT_NAME',
            5 => 'PROVINCE_NAME',
        ];
     
        $order = ' ORDER BY ' . $columns[$_REQUEST['order'][0]['column']] . ' ' . strtoupper($_REQUEST['order'][0]['dir']);
    } else {
        $order = ' ORDER BY DISTRICT_NAME ASC';
    }
     
    $output['debug']['parameters'] = $parameters;
     
    /* Total records, before filtering */
    $sql = 'SELECT COUNT(d.DISTRICT_ID)' . $from;
    try {
        $output['debug']['sqlCount'] = $sql;
        $stmt = $dns->prepare($sql);
        $stmt->execute($parameters);
        $output['recordsTotal'] = (int) $stmt->fetchColumn(0);
    } catch (PDOException $e) {
        exit($e->getMessage());
    }
     
    /* Total records, after filtering */
    $sql = 'SELECT COUNT(d.DISTRICT_ID)' . $from . $where;
    try {
        $output['debug']['sqlCount'] = $sql;
        $stmt = $dns->prepare($sql);
        $stmt->execute($parameters);
        $output['recordsFiltered'] = (int) $stmt->fetchColumn(0);
    } catch (PDOException $e) {
        exit($e->getMessage());
    }
     
    /* data */
    if ($output['recordsTotal'] > 0) {
        $sql = 'SELECT d.enable, d.DISTRICT_ID, d.DISTRICT_CODE, d.DISTRICT_NAME, p.PROVINCE_NAME' . $from . $where . $order . " LIMIT " . $_REQUEST['start'] . ", " . $_REQUEST['length'] . ";";
     
        try {
            $output['debug']['sqlResult'] = $sql;
            $stmt = $dns->prepare($sql);
            $stmt->execute($parameters);
            $output['data'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            exit($e->getMessage());
        }
    }
     
    /* unset debug for security */
    unset($output['debug']);
     
    header('Content-type: application/json; charset=utf-8');
    echo json_encode($output);
    

อ่านเพิ่มเติม

About the author

phunsanit administrator

Leave a Reply