DataTables Part4 -Individual column searching-

前回までに引き続きDataTablesについて。今回は各列ごとに独自に検索窓を設ける方法。

これまでの投稿は下記の通り。

  • Part1 -Introduction-
  • Part2 -Server-side processing-
  • Part3 -File Export-
  •  

    基本的にはPart2 -Server-side processing-のソースがベースとなる。
    まず、通常のHTMLファイルを用意する。thead内に検索用inputタグやselectタグを設置。

        <table id="example" class="display" width="100%" cellspacing="0">
            <thead>
                <tr>
                    <th>CountryCode</th>
                    <th>Language</th>
                    <th>IsOfficial</th>
                    <th>Percentage</th>
                </tr>
                <tr>
                    <td>
                        <input type="text" data-column="0" class="search-input-text">
                    </td>
                    <td>
                        <input type="text" data-column="1" class="search-input-text">
                    </td>
                    <td>
                        <select data-column="2" class="search-input-select">
                            <option value="">All</option>
                            <option value="1">T</option>
                            <option value="2">F</option>
                        </select>
                    </td>
                    <td>
                        <input type="text" data-column="3" class="search-input-text">
                    </td>
                </tr>
            </thead>
        </table>
    

     
    次に、javascriptの編集。
    今回はヘッダの下の行に検索窓をおくことにする。この場合、orderCellsTopをtrueにしておかないと、検索窓のところにOrdering機能が設置されてしまうので注意。
    また、どの列の検索窓に検索ワードが打ち込まれたかを検知するための記述をする。

    $(document).ready(function(){
        $('#example').DataTable( {
            /**
             * Part1~3で説明済み
             */
            dom: '<"top"f>rt<"bottom"lip><"clear">',
            lengthMenu: [[10, 50, 100, 500, 9999], [10, 50, 100, 500, "全"]],
            language: {
                url: "https://cdn.datatables.net/plug-ins/1.10.15/i18n/Japanese.json",
            },
            stateSave: true,
            serverSide: true,
            ajax: "datatables_griddata4.php",
    
            /**
             * 一番上のヘッダーセルにOrdering機能を持ってくる
             * (false(default)の場合は一番下)
             */
            orderCellsTop: true,
    
        } );
    
        /**
         * Individual column filtering
         * 各カラムでインスタント検索を行う
         */
        $('#example').on( 'click', '.search-input-text', function (e) {
            e.stopPropagation();
        } );
    
        $('#example').on( 'keyup change', '.search-input-text', function (e) {
            var i =$(this).attr('data-column');  // getting column index
            var v =$(this).val();  // getting search input value
            dataTable.columns(i).search(v).draw();
        } );
    
        $('#example').on( 'change', '.search-input-select', function (e) {
            var i =$(this).attr('data-column');  // getting column index
            var v =$(this).val();  // getting search input value
            dataTable.columns(i).search(v).draw();
        } );
    });
    

     

    Part2で使用していた “datatables_griddata1.php” をベースに “datatables_griddata4.php” として書き換える。以下は変更点のみ記載。

        /**
         * SQL for Individual column filtering
         */
        $sql_individual_filtering = "";
        if ( !empty($requestData['columns'][0]['search']['value']) ) {
            $sql_individual_filtering .= " AND CountryCode LIKE :col0 ESCAPE '!'";
        }
        if ( !empty($requestData['columns'][1]['search']['value']) ) {
            $sql_individual_filtering .= " AND Language LIKE :col1 ESCAPE '!'";
        }
        if ( !empty($requestData['columns'][2]['search']['value']) ) {
            if ($requestData['columns'][2]['search']['value'] == 1) {
                $sql_individual_filtering .= " AND IsOfficial = 'T'";
            } else if ($requestData['columns'][2]['search']['value'] == 2) {
                $sql_individual_filtering .= " AND IsOfficial = 'F'";
            }
        }
        if ( !empty($requestData['columns'][3]['search']['value']) ) {
            $sql_individual_filtering .= " AND Percentage LIKE :col3 ESCAPE '!'";
        }
    
    
        /**
         * Number of results after Individual column filtering
         */
        $sql_filtered_cnt = "SELECT count(*) as reccnt FROM countrylanguage
                             WHERE 1 = 1 {$sql_individual_filtering}";
    
        if (!empty($sql_individual_filtering)) {
            $stmt_num = $pdo->prepare($sql_filtered_cnt);
            if ( !empty($requestData['columns'][0]['search']['value']) ) {
                $stmt_num->bindValue(col0, '%' . preg_replace('/(?=[!_%])/', '!', $requestData['columns'][0]['search']['value']) . '%');
            }
            if ( !empty($requestData['columns'][1]['search']['value']) ) {
                $stmt_num->bindValue(col1, '%' . preg_replace('/(?=[!_%])/', '!', $requestData['columns'][1]['search']['value']) . '%');
            }
            if ( !empty($requestData['columns'][3]['search']['value']) ) {
                $stmt_num->bindValue(col3, '%' . preg_replace('/(?=[!_%])/', '!', $requestData['columns'][3]['search']['value']) . '%');
            }
            $stmt_num->execute();
        } else {
            $stmt_num = $pdo->query($sql_filtered_cnt);
        }
        $totalFiltered = $stmt_num->fetchColumn();
    

     

        $sql = "SELECT CountryCode, Language, IsOfficial, Percentage
                FROM countrylanguage
                WHERE 1 = 1 {$sql_individual_filtering}
                ORDER BY $order_col $order_dir
                LIMIT :st, :len";
        $stmt = $pdo->prepare($sql);
    
        if (!empty($sql_individual_filtering)) {
            if ( !empty($requestData['columns'][0]['search']['value']) ) {
                $stmt->bindValue(col0, '%' . preg_replace('/(?=[!_%])/', '!', $requestData['columns'][0]['search']['value']) . '%');
            }
            if ( !empty($requestData['columns'][1]['search']['value']) ) {
                $stmt->bindValue(col1, '%' . preg_replace('/(?=[!_%])/', '!', $requestData['columns'][1]['search']['value']) . '%');
            }
            if ( !empty($requestData['columns'][3]['search']['value']) ) {
                $stmt->bindValue(col3, '%' . preg_replace('/(?=[!_%])/', '!', $requestData['columns'][3]['search']['value']) . '%');
            }
        }
    

     

    具体的な動きはこちら。