Component

Module

DataTable (Filtering Funtion)

Add filter funtion to your dataTable

Directory

File Folder Link
index.php \\SYNAS\Allan\DOCUMENTATION\Component\DataTable (Filtering Function)\rckuc\wolf\app\views\option
style.css \\SYNAS\Allan\DOCUMENTATION\Component\DataTable (Filtering Function)\rckuc\wolf\admin\themes\black_and_white
backend.js & dataTable.js \\SYNAS\Allan\DOCUMENTATION\Component\DataTable (Filtering Function)\rckuc\wolf\admin\javascript
backend.php \\SYNAS\Allan\DOCUMENTATION\Component\DataTable (Filtering Function)\rckuc\wolf\app\layouts

 

Step 1

Update: index.php

In any of your index.php files, make sure your table has the following setup:

  1. Add an id="site-list" to your <table>.
    • This enables the DataTable functionality.
  2. Assign one of the following classes to your table header cells (<th>):
    • filterColumn — Creates a dropdown filter inside the filter container.
    • filterDate — Use this for date columns only. It will add Start Date and End Date inputs to the filter container.
    The JavaScript will automatically create a filter container and prepend it to your <form>.

    Below example I added .filterColumn at Category and .filterDate at Date Added
<form id="option_form" name="thisform" method="post" action="<?php echo get_url('option/save_order') ?>"> <div align=right><input type=submit value="<?php echo __('Save Order'); ?>"></div> <table id="sites-list" class="index" cellpadding="0" cellspacing="0" border="0"> <thead> <tr> <th></th> <!-- add an extra <th> for checkbox column --> <th class="files"><?php echo __('Name'); ?></th> <th class="files filterColumn"><?php echo __('Category'); ?></th> <th class="size"><?php echo __('Order'); ?></th> <th class="size filterDate" width=100><?php echo __('Date Added'); ?></th> <th class="modify" width=50><?php echo __('Action'); ?></th> </tr> </thead>
<form id="option_form" name="thisform" method="post" action="<?php echo get_url('option/save_order') ?>">
    <div align=right><input type=submit value="<?php echo __('Save Order'); ?>"></div>
    <table id="sites-list" class="index" cellpadding="0" cellspacing="0" border="0">
      <thead>
        <tr>
          <th></th> <!-- add an extra <th> for checkbox column -->
          <th class="files"><?php echo __('Name'); ?></th>
          <th class="files filterColumn"><?php echo __('Category'); ?></th>
          <th class="size"><?php echo __('Order'); ?></th>
          <th class="size filterDate" width=100><?php echo __('Date Added'); ?></th>
          <th class="modify" width=50><?php echo __('Action'); ?></th>
        </tr>
      </thead>

Step 2

Update: style.css

/* dataTable Filter */ #filter_dataTable { background-color: #f5f5f5; padding: 1rem; border-radius: 12px; box-shadow: 0 2px 6px rgba(0,0,0,0.08); display: flex; align-items: center; justify-content: flex-start; flex-wrap: wrap; gap: 1rem; margin-bottom: 1rem; } #filter_dataTable h3 { flex: 0 0 100%; margin: 0; } #filter_dataTable > div { display: flex; align-items: center; justify-content: center; gap: 0.5rem; }
/* dataTable Filter */
#filter_dataTable {
    background-color: #f5f5f5;
    padding: 1rem;
    border-radius: 12px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.08);
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1rem;
}

#filter_dataTable h3 {
    flex: 0 0 100%;
    margin: 0;
}

#filter_dataTable > div {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

Step 3

Update: backend.js

// Jquery 'DataTable' apply to all index.php table $(document).ready(function() { // if this table have 'order' column then set ordering to <td> $('#sites-list tbody td').each(function () { let $input = $(this).find('input[name="order[]"]'); if ($input.length) { $(this).attr('data-order', $input.val()); } }); let tableConfig = { lengthMenu: [ [10, 25, 50, 100, -1], [10, 25, 50, 100, 'All'] ] }; // Optional - Add searching: false only if inside form#gallery_list if ($("form#gallery_list").length) { tableConfig.searching = false; } // Optional - Add 'copy', 'csv', 'excel', 'pdf', 'print' function only if inside form#option_form if ($("form#option_form").length) { tableConfig.dom = 'lfrtBip'; tableConfig.buttons = ['copy', 'csv', 'excel', 'pdf', 'print']; } // Detect sort column priority let $ths = $('#sites-list thead th'); let orderCol = $ths.filter('.size').index(); // "Order" let dateCol = $ths.filter('.filterDate').index(); // "Date Added" let sortCol = orderCol >= 0 ? orderCol : (dateCol >= 0 ? dateCol : 0); // Default order tableConfig.order = [[sortCol, 'asc']]; window.sitesTable = $('#sites-list').DataTable(tableConfig); // Check if any dataTable having th.filterColumn // If yes then prepend filter dropdown to <form> let $filter_container = $('<div id="filter_dataTable"><h3>Filter</h3></div>'); if ($('table#sites-list th.filterColumn').length) { $('table#sites-list th.filterColumn').each(function() { let colName = $(this).text().trim(); let colIndex = $(this).index(); let $label = $('<label></label>').text(colName + ":"); let $select = $('<select class="textbox" data-col-index="'+colIndex+'"><option>All</option></select>'); let allValues = window.sitesTable.column(colIndex).data().toArray(); let uniqueValues = [...new Set(allValues.map(v => v.trim()))].sort((a, b) => a.localeCompare(b)); uniqueValues.forEach(v => { if (v) $select.append('<option value="' + v + '">' + v + '</option>'); }); $filter_container.append($('<div></div>').append($label).append($select)); }); $('table#sites-list').parents('form').prepend($filter_container); } // Check if any dataTable having th.filterDate // If yes then append start date & end date to div#filter_dataTable if ($('table#sites-list th.filterDate').length) { let startDate = '<div><label>Start Date:</label><input class="textbox" type="date" id="minDate"></div>'; let endDate = '<div><label>End Sate:</label><input class="textbox" type="date" id="maxDate"></div>'; if ($("div#filter_dataTable").length) { $("div#filter_dataTable").append(startDate).append(endDate); } else { filter_container.append(startDate).append(endDate); $('table#sites-list').parents('form').prepend($filter_container); } } // Normalize Date function normalizeDate(d) { if (!d) return null; d.setHours(0, 0, 0, 0); // strip time return d; } // If div#filter_dataTable prepended to <form> then start filter if ($("#filter_dataTable").length) { $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) { // --------- Dropdown filters ---------- let dropdownPass = true; $('#filter_dataTable select').each(function() { let selected = $(this).val(); if (!selected || selected === "All") return; const colIndex = $(this).data('col-index'); const cellValue = data[colIndex].trim(); if (cellValue !== selected) { dropdownPass = false; return false; // break loop early } }); // If any dropdown filter fails, skip row if (!dropdownPass) return false; // --------- Date range filter ---------- const minVal = $('#minDate').val(); const maxVal = $('#maxDate').val(); if (minVal || maxVal) { const dateColumn = $('#sites-list thead th.filterDate').index(); const rowDateRaw = data[dateColumn].trim(); const rowDate = normalizeDate(new Date(rowDateRaw)); if (isNaN(rowDate)) return false; let min = minVal ? normalizeDate(new Date(minVal)) : null; let max = maxVal ? normalizeDate(new Date(maxVal)) : null; if ((min && rowDate < min) || (max && rowDate > max)) return false; } return true; // Row passes all filters }); // When any dropdown changes, redraw $('#filter_dataTable').on('change', 'select, #minDate, #maxDate', function() { window.sitesTable.draw(); }); // Show error if minDate > maxDate $(document).on('change', '#minDate, #maxDate', function() { let minDate = $('#minDate').val(); let maxDate = $('#maxDate').val(); if (minDate && maxDate) { let min = new Date(minDate); let max = new Date(maxDate); if (max < min) { Swal.fire({ icon: 'warning', title: 'Invalid date range', confirmButtonColor: '#3085d6', confirmButtonText: 'Close', text: 'End date must be the same as or after the start date.' }).then((result) => { $(this).val("") }); return; } } }); } })
// Jquery 'DataTable' apply to all index.php table
$(document).ready(function() {
    // if this table have 'order' column then set ordering to <td>
    $('#sites-list tbody td').each(function () {
        let $input = $(this).find('input[name="order[]"]');
        if ($input.length) {
            $(this).attr('data-order', $input.val());
        }
    });

    let tableConfig = {
        lengthMenu: [
            [10, 25, 50, 100, -1],
            [10, 25, 50, 100, 'All']
        ]
    };

    // Optional - Add searching: false only if inside form#gallery_list
    if ($("form#gallery_list").length) {
        tableConfig.searching = false;
    }

    // Optional - Add 'copy', 'csv', 'excel', 'pdf', 'print' function only if inside form#option_form
    if ($("form#option_form").length) {
        tableConfig.dom = 'lfrtBip';
        tableConfig.buttons = ['copy', 'csv', 'excel', 'pdf', 'print'];
    }

    // Detect sort column priority
    let $ths = $('#sites-list thead th');
    let orderCol = $ths.filter('.size').index();        // "Order"
    let dateCol  = $ths.filter('.filterDate').index();  // "Date Added"
    let sortCol  = orderCol >= 0 ? orderCol : (dateCol >= 0 ? dateCol : 0);

    // Default order
    tableConfig.order = [[sortCol, 'asc']];

    window.sitesTable = $('#sites-list').DataTable(tableConfig);

    // Check if any dataTable having th.filterColumn
    // If yes then prepend filter dropdown to <form> 
    let $filter_container = $('<div id="filter_dataTable"><h3>Filter</h3></div>');
    if ($('table#sites-list th.filterColumn').length) {

        $('table#sites-list th.filterColumn').each(function() {
            let colName = $(this).text().trim();
            let colIndex = $(this).index();

            let $label = $('<label></label>').text(colName + ":");
            let $select = $('<select class="textbox" data-col-index="'+colIndex+'"><option>All</option></select>');

            let allValues = window.sitesTable.column(colIndex).data().toArray();
            let uniqueValues = [...new Set(allValues.map(v => v.trim()))].sort((a, b) => a.localeCompare(b));

            uniqueValues.forEach(v => {
                if (v) $select.append('<option value="' + v + '">' + v + '</option>');
            });

            $filter_container.append($('<div></div>').append($label).append($select));
        });

        $('table#sites-list').parents('form').prepend($filter_container);
    }

    // Check if any dataTable having th.filterDate
    // If yes then append start date & end date to div#filter_dataTable
    if ($('table#sites-list th.filterDate').length) {
        let startDate = '<div><label>Start Date:</label><input class="textbox" type="date" id="minDate"></div>';
        let endDate = '<div><label>End Sate:</label><input class="textbox" type="date" id="maxDate"></div>';
        if ($("div#filter_dataTable").length) {
            $("div#filter_dataTable").append(startDate).append(endDate);
        } else {
            filter_container.append(startDate).append(endDate);
            $('table#sites-list').parents('form').prepend($filter_container);
        }
    }

    // Normalize Date
    function normalizeDate(d) {
        if (!d) return null;
        d.setHours(0, 0, 0, 0); // strip time
        return d;
    }

    // If div#filter_dataTable prepended to <form> then start filter
    if ($("#filter_dataTable").length) {
        $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {

            // --------- Dropdown filters ----------
            let dropdownPass = true;
            $('#filter_dataTable select').each(function() {
                let selected = $(this).val();
                if (!selected || selected === "All") return;

                const colIndex = $(this).data('col-index');
                const cellValue = data[colIndex].trim();

                if (cellValue !== selected) {
                    dropdownPass = false;
                    return false; // break loop early
                }
            });

            // If any dropdown filter fails, skip row
            if (!dropdownPass) return false;

            // --------- Date range filter ----------
            const minVal = $('#minDate').val();
            const maxVal = $('#maxDate').val();

            if (minVal || maxVal) {
                const dateColumn = $('#sites-list thead th.filterDate').index();
                const rowDateRaw = data[dateColumn].trim();
                const rowDate = normalizeDate(new Date(rowDateRaw));

                if (isNaN(rowDate)) return false;

                let min = minVal ? normalizeDate(new Date(minVal)) : null;
                let max = maxVal ? normalizeDate(new Date(maxVal)) : null;

                if ((min && rowDate < min) || (max && rowDate > max)) return false;
            }

            return true; // Row passes all filters
        });


        // When any dropdown changes, redraw
        $('#filter_dataTable').on('change', 'select, #minDate, #maxDate', function() {
            window.sitesTable.draw();
        });

        // Show error if minDate > maxDate
        $(document).on('change', '#minDate, #maxDate', function() {
            let minDate = $('#minDate').val();
            let maxDate = $('#maxDate').val();
    
            if (minDate && maxDate) {
                let min = new Date(minDate);
                let max = new Date(maxDate);
    
                if (max < min) {
                    Swal.fire({
                        icon: 'warning',
                        title: 'Invalid date range',
                        confirmButtonColor: '#3085d6',
                        confirmButtonText: 'Close',
                        text: 'End date must be the same as or after the start date.'
                    }).then((result) => {
                        $(this).val("")
                    });
                    return;
                }
            }
        });
    }
})

Step 4

Update: backend.php
Add script link in <head>

<!-- backend.php --> <head> <!-- DataTables CSS --> <link rel="stylesheet" href="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/jquery.dataTables-1.13.6.min.css"></link> <link rel="stylesheet" href="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/buttons.dataTables-2.4.1.min.css"></link> <!-- DataTables JS --> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/jquery.dataTables-1.13.6.min.js"></script> <!-- DataTables Buttons Extension (Feature for Print, Copy, Download Excel & PDF & CSV)--> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/dataTables.buttons-2.4.1.min.js"></script> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/jszip-3.10.1.min.js"></script> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/pdfmake-0.2.7.min.js"></script> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/vfs_fonts-0.2.7.js"></script> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/buttons.html5-2.4.1.min.js"></script> <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/buttons.print-2.4.1.min.js"></script> </head>
  <!-- backend.php -->
  <head>
    <!-- DataTables CSS -->
    <link rel="stylesheet" href="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/jquery.dataTables-1.13.6.min.css"></link>
    <link rel="stylesheet" href="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/buttons.dataTables-2.4.1.min.css"></link>
    
    <!-- DataTables JS -->
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/jquery.dataTables-1.13.6.min.js"></script>
    
    <!-- DataTables Buttons Extension (Feature for Print, Copy, Download Excel & PDF & CSV)-->
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/dataTables.buttons-2.4.1.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/jszip-3.10.1.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/pdfmake-0.2.7.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/vfs_fonts-0.2.7.js"></script>
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/buttons.html5-2.4.1.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="<?php echo URI_PUBLIC; ?>wolf/admin/javascripts/buttons.print-2.4.1.min.js"></script>
  </head>
Code Copied To Clipboard!