Site icon Sariful Islam

Row Selection and ‘Select All’ in jQuery DataTables

Row Selection and 'Select All' in jQuery DataTables

Row Selection and 'Select All' in jQuery DataTables

When working with large datasets in web applications, efficient data management becomes essential. One of the most useful features in jQuery DataTables is row selection and the “Select All” option, which allows users to quickly select multiple rows across pages. In this blog, we’ll explore how to implement row selection and “Select All” functionality in DataTables, ensuring it works seamlessly with pagination and filters.

 

This blog walks you through creating a DataTable with row selection capabilities, handling the ‘Select All’ checkbox, and ensuring proper selection of rows not visible due to pagination or filtering.

We’ll cover the problem, the solution, and the reasoning behind each step.

Why Implementing Row Selection and ‘Select All’ in jQuery DataTables is Challenging

jQuery DataTables makes it easy to display and interact with data, but managing rows that aren’t visible on the current page can be challenging.

This is especially important if you’re dealing with large datasets where pagination and filtering are necessary

Here are some of the common issues:

  1. Non-visible rows: The DOM only renders the rows that are currently visible. This means if you try to use regular DOM methods to interact with non-visible rows (like selecting or deselecting them), you won’t be able to do so directly.
  2. Multiple pages: DataTables will only render one page of data at a time. If your table spans multiple pages, selecting rows across these pages can be challenging.
  3. Filters: When you apply filters, the table only shows rows that match the filter, which means any selections made before filtering might be lost.

The Scenario

Let’s assume we have a customer management system where we want to display customer details in a paginated table. The user should be able to select individual rows, and a “Select All” checkbox should allow them to select all rows, even those that are not currently visible due to pagination or filtering.

The Table

We have a table with the following columns:

The first column contains checkboxes for selecting rows, and a “Select All” checkbox in the header allows the user to select all rows at once.

The Challenge

The main challenge is ensuring that the “Select All” checkbox works properly across multiple pages and filters. For example, if a user selects all rows on page 1, goes to page 2, and selects more rows, the selections should be saved. Similarly, if the user applies a filter and then selects rows, the selection should include both filtered and non-filtered rows.

Let’s now dive into the solution.

Setting Up the DataTable

We’ll start by initializing the DataTable with AJAX data and defining columns. We’ll also include the first column with checkboxes for row selection.

const customer_view_modal = $("#customer_view_modal").DataTable({
    ajax: {
        url: "/api/customers/improved-customer",
    },
    dom: "Bfrtip",
    buttons: ["pageLength", "colvis", "copy", "csv", "excel"],
    columns: [
        {
            sorting: false,
            ordering: false,
            orderable: false,
            title: `<input type="checkbox" class="select_customer_table_select_all" data-toggle="tooltip" data-title="Select All">`,
            visible: false,
            className: "text-center",
            data: {
                _: "id",
                display({ name }) {
                    return `<input type="checkbox" class="select_customer_table_row" data-toggle="tooltip" data-title="${name}">`;
                }
            },
        },
        {
            title: "Id",
            data: "id"
        },
        {
            title: "Name",
            data: "name"
        },
        {
            title: "GSTIN",
            data: "gstin"
        },
        {
            title: "Address",
            data: "address",
            visible: false,
        },
        {
            visible: false,
            title: "Mobile",
            data: "mobile"
        },
        {
            visible: false,
            title: "Email",
            data: "email"
        },
        {
            visible: false,
            title: "State",
            data: "state_name"
        },
        {
            title: "Action",
            className: "text-center",
            data: {
                _: "id",
                display() {
                    return `<button class="btn btn-success btn-sm edit_item"><i class="fa fa-pencil-alt"></i></button>
                            <button class="btn btn-danger btn-sm delete_item"><i class="fa fa-trash"></i></button>`;
                }
            }
        },
    ],
    rowCallback(row, data) {
        if (data.isSelected) {
            $(row).find(".select_customer_table_row").prop("checked", true);
            $(row).addClass("selected");
        } else {
            $(row).find(".select_customer_table_row").prop("checked", false);
            $(row).removeClass("selected");
        }
    }
});

In this setup, the rowCallback function is used to ensure that each row’s checkbox reflects the correct selection state based on a custom isSelected property in the data.

Row Selection and ‘Select All’ in DataTables:

1. Handling Row Selection

Next, we handle individual row selection. When a user clicks a checkbox to select or deselect a row, we update the isSelected property in the row’s data, and modify the DOM accordingly.

$("body").on("change", "#customer_view_modal .select_customer_table_row", function () {    
    const rowData = customer_view_modal.row($(this).parents("tr")).data();
    if ($(this).is(":checked")) {
        rowData.isSelected = true;
        $(this).parents("tr").addClass("selected");
    } else {
        rowData.isSelected = false;
        $(this).parents("tr").removeClass("selected");
        $(".select_customer_table_select_all").prop("checked", false);
    }
});

Here, we update the isSelected property of the row’s data when the checkbox state changes, ensuring that the selection state is preserved even when the row is not currently visible in the DOM.

2. Implementing the “Select All” Checkbox

The “Select All” functionality is where the real challenge lies. We need to make sure that clicking the ‘Select All’ checkbox selects all rows, whether they are visible or not.

$("body").on("change", "#customer_view_modal .select_customer_table_select_all", function (e) {
    e.preventDefault();
    e.stopPropagation();
    const isChecked = $(this).is(":checked");

    if (isChecked) {
        const rows = customer_view_modal.rows({ filter: "applied" });
        const nodes = customer_view_modal.rows().nodes();

        rows.every(function () {
            const data = this.data();
            data.isSelected = true;
        });

        $(nodes).find(".select_customer_table_row").prop("checked", true);
        $(nodes).addClass("selected");
    } else {
        const rows = customer_view_modal.rows();
        const selected_nodes = customer_view_modal.rows(".selected").nodes();

        rows.every(function () {
            const data = this.data();
            data.isSelected = false;
        });

        $(selected_nodes).find(".select_customer_table_row").prop("checked", false);
        $(selected_nodes).removeClass("selected");
    }
});

Explanation for Row Selection and ‘Select All’ in DataTables:

  1. Handling Visible Rows: We use customer_view_modal.rows({ filter: "applied" }) to get the rows that are currently visible and apply the selection.
  2. Handling All Rows: Whether visible or not, we update the isSelected property for all rows using rows.every(), ensuring the selection state is stored in the data.
  3. DOM Updates: We update the DOM only for the currently visible rows using rows().nodes().

Retrieving Selected Rows

Finally, let’s retrieve the selected rows when the user clicks a button (e.g., to send a WhatsApp message).

$("#sendWhatsApp").on("click", function () {
    const tableData = customer_view_modal.data().toArray();
    const selected_rows = tableData.filter(obj => obj.isSelected);
    console.log(selected_rows);
});

This will provide an array of all selected rows, including those that aren’t currently visible.

Conclusion

Handling row selection and the ‘Select All’ functionality in jQuery DataTables can be challenging, especially with paginated and filtered data.

However, with the right approach, it becomes manageable.

By using DataTables’ internal data structure and APIs, you can correctly manage both visible and non-visible rows.

This ensures that selection states remain intact across pagination and filters.

This method allows for seamless user interaction, even in large datasets, while keeping the DOM manipulation efficient and lightweight.

Happy coding!

Summary
Article Name
Row Selection and 'Select All' in jQuery DataTables
Author
Publisher Name
Zubizi Web Solutions
Publisher Logo