New to Kendo UI for jQueryStart a free 30-day trial

Keeping "Check All" Checkbox Active and Check Only the Visible Nodes in Kendo UI for jQuery DropDownTree

Updated on Oct 27, 2025

Environment

ProductKendo UI for jQuery DropDownTree
Version2025.3.1002

Description

I want to keep the "Check All" checkbox visible and functional in the Kendo UI for jQuery DropDownTree component even when filtering is applied. The goal is to select all visible leaf nodes based on the filter while excluding non-visible items.

This knowledge base article also answers the following questions:

  • How to implement custom "Check All" functionality for filtered items in Kendo UI for jQuery DropDownTree?
  • How to make the "Check All" checkbox persist in DropDownTree with filters?
  • How to select the filtered leaf nodes in DropDownTree?
  • How to check only the visible nodes?

Solution

To achieve this, create a custom "Check All" checkbox and add it to the DropDownTree popup. Implement logic to check/uncheck visible items filtered in the pop-up.

Steps

  1. Add Custom Checkbox in the Popup
    Use the open event of the DropDownTree to create and add the custom checkbox.

    javascript
    open: function (e) {
        setTimeout(() => createCustomCheckbox(e.sender), 50);
    }
    
    function createCustomCheckbox(ddtree) {
        const customCheckboxHtml = `
            <div class="k-check-all custom-check-all" style="padding: 8px; border-bottom: 1px solid #ddd;">
                <span class="k-checkbox-wrap">
                    <input type="checkbox" id="checkAllCustom" class="k-checkbox-lg k-rounded-md k-checkbox">
                    <label for="checkAllCustom" class="k-checkbox-label" style="margin-left: 4px;">Check All Custom</label>
                </span>
            </div>
        `;
    
        $(".custom-check-all").remove(); // Remove existing custom checkbox
    
        const filterElement = ddtree.popup.element.find(".k-list-filter");
        if (filterElement.length > 0) {
            $(customCheckboxHtml).insertAfter(filterElement);
        } else {
            ddtree.popup.element.prepend(customCheckboxHtml);
        }
    
        $("#checkAllCustom").off("change").on("change", function () {
            handleCustomCheckAll(ddtree, $(this).is(":checked"));
        });
    }
  2. Handle "Check All" Logic
    Implement the logic to select or deselect filtered leaf nodes.

    javascript
    function handleCustomCheckAll(ddtree, isChecked) {
        const checkedItems = new Set(); // Track checked items
    
        ddtree.dataSource.view().forEach(item => {
            if (item.hasChildren) {
                item.items.forEach(child => {
                    if (child.visible) {
                        isChecked? checkedItems.add(child.text) : checkedItems.delete(child.text);
                    }
                });
            } else if (item.visible) {
                isChecked ? checkedItems.add(item.text) : checkedItems.delete(item.text);
            }
        });
    
        // Update the selection in the DropDownTree
        ddtree.value([...checkedItems]);
    }
  3. Ensure Checkbox Visibility During Filtering
    Use the filtering event to re-create the custom checkbox when filtering is applied.

    javascript
    filtering: function (e) {
        createCustomCheckbox(e.sender);
    }
  4. Example


    <input id="dropdowntree" />

    <script>
      // Store checked states to preserve them during filtering
      let checkedStates = new Set();

      // Helper function to find a checkbox in a node
      function findCheckbox(node) {
        let checkbox = node.find("input[type='checkbox']").first();
        if (checkbox.length === 0) {
          checkbox = node.find(".k-checkbox").first();
        }
        return checkbox;
      }

      // Helper function to determine if a node should be included
      function shouldIncludeNode(ddtree, node, dataItem) {
        const filterValue = ddtree.filterInput ? ddtree.filterInput.val() : "";

        // If no filter, only include visible nodes (original behavior)
        if (!filterValue) {
          return node.is(":visible");
        }

        // With filter: include if node matches filter OR if it's a parent node
        const matchesFilter = dataItem.text
          .toLowerCase()
          .includes(filterValue.toLowerCase());
        const isParent = dataItem.items && dataItem.items.length > 0;

        return matchesFilter || isParent;
      }

      // Function to save current checked states
      function saveCheckedStates(ddtree) {
        checkedStates.clear();
        const treeview = ddtree.treeview;
        const checkedNodes = treeview.element.find(
          "input[type='checkbox']:checked",
        );

        checkedNodes.each(function () {
          const node = $(this).closest("li");
          const dataItem = treeview.dataItem(node);
          if (dataItem) {
            checkedStates.add(dataItem.text);
          }
        });
      }

      // Function to handle custom check all functionality
      function handleCustomCheckAll(ddtree, isChecked) {
        const treeview = ddtree.treeview;
        const allNodes = treeview.element.find("li");

        allNodes.each(function () {
          const node = $(this);
          const dataItem = treeview.dataItem(node);

          if (!dataItem || !shouldIncludeNode(ddtree, node, dataItem)) return;

          let checkbox = findCheckbox(node);

          if (checkbox.length > 0 && !dataItem.get("disabled")) {
            checkbox.prop("checked", isChecked);
            node.attr("aria-checked", isChecked);

            // Update stored states
            if (isChecked) {
              checkedStates.add(dataItem.text);
            } else {
              checkedStates.delete(dataItem.text);
            }

            checkbox.trigger("change");
          }
        });

        setTimeout(() => ddtree.trigger("change"), 50);
      }

      // Function to create and insert a custom checkbox
      function createCustomCheckbox(ddtree) {
        const customCheckboxHtml = `
        <div class="k-check-all custom-check-all" style="padding: 8px; border-bottom: 1px solid #ddd;">
          <span class="k-checkbox-wrap">
            <input type="checkbox" id="checkAllCustom" class="k-checkbox-lg k-rounded-md k-checkbox">
            <label for="checkAllCustom" class="k-checkbox-label" style="margin-left: 4px;">Check All Custom</label>
          </span>
        </div>
      `;

        $(".custom-check-all").remove();

        const filterElement = ddtree.popup.element.find(".k-list-filter");
        if (filterElement.length > 0) {
          $(customCheckboxHtml).insertAfter(filterElement);
        } else {
          ddtree.popup.element.prepend(customCheckboxHtml);
        }

        $("#checkAllCustom")
          .off("change")
          .on("change", function () {
            handleCustomCheckAll(ddtree, $(this).is(":checked"));
          });
      }

      $("#dropdowntree").kendoDropDownTree({
        autoClose: false,
        open: function (e) {
          setTimeout(() => createCustomCheckbox(e.sender), 50);
        },

        filtering: function (e) {
          const ddtree = e.sender;
          saveCheckedStates(ddtree);
          setTimeout(() => {
            createCustomCheckbox(ddtree);
          }, 50);
        },

        dataBound: function (e) {
          const ddtree = e.sender;
          setTimeout(() => {
            if ($("#checkAllCustom").length > 0) {
            }
          }, 50);
        },

        check: function (e) {
          const ddtree = e.sender;
          const node = $(e.node);
          const dataItem = ddtree.treeview.dataItem(node);
          const checkbox = findCheckbox(node);
          const isChecked = checkbox.is(":checked");

          if (dataItem) {
            if (isChecked) {
              checkedStates.add(dataItem.text);
            } else {
              checkedStates.delete(dataItem.text);
            }
          }
        },

        dataSource: [
          {
            text: "Bedroom",
            value: "bedroom",
            items: [
              { text: "Queen-size bed", value: "queen-size-bed" },
              { text: "Single bed", value: "single-bed" },
            ],
          },
          {
            text: "Furniture",
            value: "furniture",
            expanded: true,
            items: [
              { text: "Tables & Chairs", value: "tables-chairs" },
              { text: "Sofas", value: "sofas" },
              { text: "Occasional Furniture", value: "occasional-furniture" },
            ],
          },
          {
            text: "Decor",
            value: "decor",
            items: [
              { text: "Bed Linen", value: "bed-linen" },
              { text: "Curtains & Blinds", value: "curtains-blinds" },
              { text: "Carpets", value: "carpets" },
            ],
          },
        ],
        checkboxes: true,
        checkAll: false,
        filter: "contains",
      });
    </script>
    <style>
      body {
        font-family: Helvetica, Arial, sans-serif;
        font-size: 14px;
      }

      .custom-check-all {
        background-color: #f8f9fa;
        border-bottom: 1px solid #dee2e6;
        position: sticky;
        top: 0;
        z-index: 10;
      }

      .custom-check-all .k-checkbox-wrap {
        display: flex;
        align-items: center;
      }

      .custom-check-all .k-checkbox-label {
        font-weight: 600;
        color: #495057;
        cursor: pointer;
      }

      .custom-check-all:hover {
        background-color: #e9ecef;
      }

      .custom-check-all .k-checkbox {
        margin-right: 8px;
      }
    </style>

The provided code demonstrates adding a custom "Check All Custom" checkbox to the DropDownTree that selects visible nodes based on filters. This implementation includes state persistence for selections even after filters are applied or cleared.

See Also