Chuyển đến nội dung chính

Hướng dẫn DataTable cơ bản: Individual Column Searching - Part 2

Trong các bài trước, chúng ta đã làm quen với ô Search tổng quát. Tuy nhiên, khi dữ liệu trở nên phức tạp, người dùng thường có nhu cầu lọc chính xác theo từng trường thông tin (ví dụ: chỉ xem sản phẩm "Hết hàng" hoặc thuộc loại "Điện tử").

Hôm nay, mình sẽ hướng dẫn các bạn cách tạo bộ lọc dạng Popup Dropdown ngay trên Header của DataTable

Chúng ta sẽ sử dụng Icon tam giác và Popup Menu của Bootstrap

graph LR subgraph "Thẻ TH (Table Header Cell)" Title[Text: Category] --- Icon[Icon: bi-caret-down-fill] end Icon -.-> Menu[Dropdown Menu - Absolute Position] subgraph "Dropdown Menu Items" Option1[Tất cả] Option2[Giá trị 1] Option3[Giá trị 2] end Menu --- Option1 Menu --- Option2 Menu --- Option3

Cài đặt giao diện CSS

Tham khảo: https://getbootstrap.com/docs/4.0/components/dropdowns/

Cấu Trúc HTML Dropdown

<div class="dropdown d-inline-block filter-container ms-2">
    <!-- Icon filter (người dùng click vào đây) -->
    <i class="bi bi-caret-down-fill filter-icon" 
       data-bs-toggle="dropdown" 
       aria-expanded="false" 
       title="Filter by Category">
    </i>

    <!-- Dropdown menu chứa các option -->
    <ul class="dropdown-menu shadow-lg" id="filter-category">
        <li><a class="dropdown-item filter-option" href="#" data-value="">All Category</a></li>
        <li><hr class="dropdown-divider"></li>
        <li><a class="dropdown-item filter-option" href="#" data-value="Fruit">Fruit</a></li>
        <li><a class="dropdown-item filter-option" href="#" data-value="Dairy">Dairy</a></li>
    </ul>
</div>

Giải thích các class:

  • dropdown- Container của dropdown (Bootstrap)
  • d-inline-block- Hiển thị inline để không chiếm full width
  • filter-container- Class custom để styling và ngăn chặn event propagation
  • ms-2- Margin-start từ Bootstrap (margin left = 8px)
  • filter-icon- Class custom cho icon
  • dropdown-menu- Menu dropdown từ Bootstrap
  • shadow-lg- Drop shadow lớn (Bootstrap utility)
  • dropdown-item- Item trong menu (Bootstrap)
  • `filter-option- Class custom để handle click event
  • dropdown-divider- Dòng ngăn cách (Bootstrap)

Filter Icon Styling

/* Container chứa tiêu đề và icon */
.filter-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: default;
}

/* Icon tam giác nhỏ */
.filter-icon {
    font-size: 0.7rem;
    cursor: pointer;
    margin-left: 8px;
    color: #e0e0e0; /* Mờ khi chưa active */
    transition: 0.3s;
}

.filter-icon:hover, .filter-active {
    color: #ffc107 !important; /* Vàng rực khi đang có filter */
}

/* Menu popup */
.dropdown-menu {
    max-height: 300px;
    overflow-y: auto;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

Triển khai JavaScript (The Logic)

Chúng ta sẽ sử dụng sự kiện initComplete để inject HTML vào Header sau khi table đã khởi tạo xong.
initComplete: function () {
    this.api().columns().every(function () {
        var column = this;
        var header = $(column.header());
        
        // Chỉ áp dụng lọc cho một số cột nhất định (ví dụ index 2 và 6)
        if (header.text() === 'Category' || header.text() === 'Status') {
            
            // Tạo cấu trúc Dropdown
            var $filterWrapper = $(`
                <div class="dropdown d-inline-block shadow-none">
                    <i class="bi bi-caret-down-fill filter-icon" data-bs-toggle="dropdown" aria-haspopup="true"></i>
                    <ul class="dropdown-menu">
                        <li><a class="dropdown-item filter-option" href="#" data-value="">(Tất cả)</a></li>
                        <li><hr class="dropdown-divider"></li>
                    </ul>
                </div>
            `);

            // Chèn vào cạnh Text của Header
            header.wrapInner('<span class="column-title"></span>').append($filterWrapper);

            // Lấy dữ liệu Unique để đổ vào menu
            column.data().unique().sort().each(function (d) {
                if (d) {
                    $filterWrapper.find('.dropdown-menu').append(
                        `<li><a class="dropdown-item filter-option" href="#" data-value="${d}">${d}</a></li>`
                    );
                }
            });

            // Xử lý sự kiện Filter
            $filterWrapper.find('.filter-option').on('click', function (e) {
                e.preventDefault();
                var val = $(this).data('value');
                
                // Đổi màu icon để báo hiệu đang filter
                var icon = $filterWrapper.find('.filter-icon');
                val !== "" ? icon.addClass('filter-active') : icon.removeClass('filter-active');

                // Search chính xác (Exact Match) bằng Regex
                column.search(val ? '^' + $.fn.dataTable.util.escapeRegex(val) + '$' : '', true, false).draw();
            });

            // Quan trọng: Ngăn chặn Sort khi click vào Icon/Menu
            $filterWrapper.on('click', function (e) {
                e.stopPropagation();
            });
        }
    });
}
Exact Match (^...$$): Khi lọc "Fruit", nếu không dùng Regex, DataTable có thể hiển thị cả "Fruit Juice".
Việc bọc giá trị trong ^ (bắt đầu) và $ (kết thúc) giúp lọc chính xác 100%.

Lưu ý khi dùng với Server-side Processing

Khi bạn bật serverSide: true, dữ liệu trả về mỗi lần chỉ có 10 dòng. Do đó, column.data().unique() sẽ chỉ hiện 10 giá trị đó.

Trong trường hợp này, hãy tạo một API riêng ở Backend trả về danh mục (Categories/Statuses) đầy đủ, sau đó dùng Ajax để đổ vào menu filter thay vì quét dữ liệu tại chỗ.

Source code: DataTable-demo

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.