| 
 | 1 | +---  | 
 | 2 | +title: Keeping "Check All" Checkbox Active and Check Only the Visible Nodes in Kendo UI for jQuery DropDownTree   | 
 | 3 | +description: Learn how to keep the "Check All" checkbox visible and functional in the Kendo UI for jQuery DropDownTree when a filter is active, enabling selection of filtered leaf nodes.  | 
 | 4 | +type: how-to  | 
 | 5 | +page_title: How to Add Custom "Check All" Functionality in Kendo UI for jQuery DropDownTree with Filter  | 
 | 6 | +meta_title: Adding Custom "Check All" Checkbox in Kendo UI for jQuery DropDownTree  | 
 | 7 | +slug: custom-check-all-checkbox-kendo-jquery-dropdowntree  | 
 | 8 | +tags: dropdowntree, kendo ui for jquery, check all, filtering, open, filtering event  | 
 | 9 | +res_type: kb  | 
 | 10 | +ticketid: 1701162  | 
 | 11 | +---  | 
 | 12 | + | 
 | 13 | +## Environment  | 
 | 14 | + | 
 | 15 | +<table>  | 
 | 16 | +  <tbody>  | 
 | 17 | +    <tr>  | 
 | 18 | +      <td>Product</td>  | 
 | 19 | +      <td>Kendo UI for jQuery DropDownTree</td>  | 
 | 20 | +    </tr>  | 
 | 21 | +    <tr>  | 
 | 22 | +      <td>Version</td>  | 
 | 23 | +      <td>2025.3.1002</td>  | 
 | 24 | +    </tr>  | 
 | 25 | +  </tbody>  | 
 | 26 | +</table>  | 
 | 27 | + | 
 | 28 | +## Description  | 
 | 29 | + | 
 | 30 | +I want to keep the "Check All" checkbox visible and functional in the [Kendo UI for jQuery DropDownTree](https://www.telerik.com/kendo-jquery-ui/documentation/controls/dropdowntree/checkboxes) component even when filtering is applied. The goal is to select all visible leaf nodes based on the filter while excluding non-visible items.  | 
 | 31 | + | 
 | 32 | +This knowledge base article also answers the following questions:  | 
 | 33 | +- How to implement custom "Check All" functionality for filtered items in Kendo UI for jQuery DropDownTree?  | 
 | 34 | +- How to make the "Check All" checkbox persist in DropDownTree with filters?  | 
 | 35 | +- How to select the filtered leaf nodes in DropDownTree?  | 
 | 36 | +- How to check only the visible nodes?  | 
 | 37 | + | 
 | 38 | +## Solution  | 
 | 39 | + | 
 | 40 | +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.  | 
 | 41 | + | 
 | 42 | +### Steps  | 
 | 43 | + | 
 | 44 | +1. **Add Custom Checkbox in the Popup**    | 
 | 45 | +   Use the [`open`](https://www.telerik.com/kendo-jquery-ui/documentation/api/javascript/ui/dropdowntree/events/open) event of the DropDownTree to create and add the custom checkbox.  | 
 | 46 | + | 
 | 47 | +   ```javascript  | 
 | 48 | +   open: function (e) {  | 
 | 49 | +       setTimeout(() => createCustomCheckbox(e.sender), 50);  | 
 | 50 | +   }  | 
 | 51 | + | 
 | 52 | +   function createCustomCheckbox(ddtree) {  | 
 | 53 | +       const customCheckboxHtml = `  | 
 | 54 | +           <div class="k-check-all custom-check-all" style="padding: 8px; border-bottom: 1px solid #ddd;">  | 
 | 55 | +               <span class="k-checkbox-wrap">  | 
 | 56 | +                   <input type="checkbox" id="checkAllCustom" class="k-checkbox-lg k-rounded-md k-checkbox">  | 
 | 57 | +                   <label for="checkAllCustom" class="k-checkbox-label" style="margin-left: 4px;">Check All Custom</label>  | 
 | 58 | +               </span>  | 
 | 59 | +           </div>  | 
 | 60 | +       `;  | 
 | 61 | + | 
 | 62 | +       $(".custom-check-all").remove(); // Remove existing custom checkbox  | 
 | 63 | + | 
 | 64 | +       const filterElement = ddtree.popup.element.find(".k-list-filter");  | 
 | 65 | +       if (filterElement.length > 0) {  | 
 | 66 | +           $(customCheckboxHtml).insertAfter(filterElement);  | 
 | 67 | +       } else {  | 
 | 68 | +           ddtree.popup.element.prepend(customCheckboxHtml);  | 
 | 69 | +       }  | 
 | 70 | + | 
 | 71 | +       $("#checkAllCustom").off("change").on("change", function () {  | 
 | 72 | +           handleCustomCheckAll(ddtree, $(this).is(":checked"));  | 
 | 73 | +       });  | 
 | 74 | +   }  | 
 | 75 | +   ```  | 
 | 76 | + | 
 | 77 | +2. **Handle "Check All" Logic**    | 
 | 78 | +   Implement the logic to select or deselect filtered leaf nodes.  | 
 | 79 | + | 
 | 80 | +   ```javascript  | 
 | 81 | +   function handleCustomCheckAll(ddtree, isChecked) {  | 
 | 82 | +       const checkedItems = new Set(); // Track checked items  | 
 | 83 | + | 
 | 84 | +       ddtree.dataSource.view().forEach(item => {  | 
 | 85 | +           if (item.hasChildren) {  | 
 | 86 | +               item.items.forEach(child => {  | 
 | 87 | +                   if (child.visible) {  | 
 | 88 | +                       isChecked? checkedItems.add(child.text) : checkedItems.delete(child.text);  | 
 | 89 | +                   }  | 
 | 90 | +               });  | 
 | 91 | +           } else if (item.visible) {  | 
 | 92 | +               isChecked ? checkedItems.add(item.text) : checkedItems.delete(item.text);  | 
 | 93 | +           }  | 
 | 94 | +       });  | 
 | 95 | + | 
 | 96 | +       // Update the selection in the DropDownTree  | 
 | 97 | +       ddtree.value([...checkedItems]);  | 
 | 98 | +   }  | 
 | 99 | +   ```  | 
 | 100 | + | 
 | 101 | +3. **Ensure Checkbox Visibility During Filtering**    | 
 | 102 | +   Use the [`filtering`](https://www.telerik.com/kendo-jquery-ui/documentation/api/javascript/ui/dropdowntree/events/filtering) event to re-create the custom checkbox when filtering is applied.  | 
 | 103 | + | 
 | 104 | +   ```javascript  | 
 | 105 | +   filtering: function (e) {  | 
 | 106 | +       createCustomCheckbox(e.sender);  | 
 | 107 | +   }  | 
 | 108 | +   ```  | 
 | 109 | + | 
 | 110 | +4. **Example**    | 
 | 111 | +    | 
 | 112 | +```dojo  | 
 | 113 | +
  | 
 | 114 | +    <input id="dropdowntree" />  | 
 | 115 | +
  | 
 | 116 | +    <script>  | 
 | 117 | +      // Store checked states to preserve them during filtering  | 
 | 118 | +      let checkedStates = new Set();  | 
 | 119 | +
  | 
 | 120 | +      // Helper function to find a checkbox in a node  | 
 | 121 | +      function findCheckbox(node) {  | 
 | 122 | +        let checkbox = node.find("input[type='checkbox']").first();  | 
 | 123 | +        if (checkbox.length === 0) {  | 
 | 124 | +          checkbox = node.find(".k-checkbox").first();  | 
 | 125 | +        }  | 
 | 126 | +        return checkbox;  | 
 | 127 | +      }  | 
 | 128 | +
  | 
 | 129 | +      // Helper function to determine if a node should be included  | 
 | 130 | +      function shouldIncludeNode(ddtree, node, dataItem) {  | 
 | 131 | +        const filterValue = ddtree.filterInput ? ddtree.filterInput.val() : "";  | 
 | 132 | +
  | 
 | 133 | +        // If no filter, only include visible nodes (original behavior)  | 
 | 134 | +        if (!filterValue) {  | 
 | 135 | +          return node.is(":visible");  | 
 | 136 | +        }  | 
 | 137 | +
  | 
 | 138 | +        // With filter: include if node matches filter OR if it's a parent node  | 
 | 139 | +        const matchesFilter = dataItem.text  | 
 | 140 | +          .toLowerCase()  | 
 | 141 | +          .includes(filterValue.toLowerCase());  | 
 | 142 | +        const isParent = dataItem.items && dataItem.items.length > 0;  | 
 | 143 | +
  | 
 | 144 | +        return matchesFilter || isParent;  | 
 | 145 | +      }  | 
 | 146 | +
  | 
 | 147 | +      // Function to save current checked states  | 
 | 148 | +      function saveCheckedStates(ddtree) {  | 
 | 149 | +        checkedStates.clear();  | 
 | 150 | +        const treeview = ddtree.treeview;  | 
 | 151 | +        const checkedNodes = treeview.element.find(  | 
 | 152 | +          "input[type='checkbox']:checked",  | 
 | 153 | +        );  | 
 | 154 | +
  | 
 | 155 | +        checkedNodes.each(function () {  | 
 | 156 | +          const node = $(this).closest("li");  | 
 | 157 | +          const dataItem = treeview.dataItem(node);  | 
 | 158 | +          if (dataItem) {  | 
 | 159 | +            checkedStates.add(dataItem.text);  | 
 | 160 | +          }  | 
 | 161 | +        });  | 
 | 162 | +      }  | 
 | 163 | +
  | 
 | 164 | +      // Function to handle custom check all functionality  | 
 | 165 | +      function handleCustomCheckAll(ddtree, isChecked) {  | 
 | 166 | +        const treeview = ddtree.treeview;  | 
 | 167 | +        const allNodes = treeview.element.find("li");  | 
 | 168 | +
  | 
 | 169 | +        allNodes.each(function () {  | 
 | 170 | +          const node = $(this);  | 
 | 171 | +          const dataItem = treeview.dataItem(node);  | 
 | 172 | +
  | 
 | 173 | +          if (!dataItem || !shouldIncludeNode(ddtree, node, dataItem)) return;  | 
 | 174 | +
  | 
 | 175 | +          let checkbox = findCheckbox(node);  | 
 | 176 | +
  | 
 | 177 | +          if (checkbox.length > 0 && !dataItem.get("disabled")) {  | 
 | 178 | +            checkbox.prop("checked", isChecked);  | 
 | 179 | +            node.attr("aria-checked", isChecked);  | 
 | 180 | +
  | 
 | 181 | +            // Update stored states  | 
 | 182 | +            if (isChecked) {  | 
 | 183 | +              checkedStates.add(dataItem.text);  | 
 | 184 | +            } else {  | 
 | 185 | +              checkedStates.delete(dataItem.text);  | 
 | 186 | +            }  | 
 | 187 | +
  | 
 | 188 | +            checkbox.trigger("change");  | 
 | 189 | +          }  | 
 | 190 | +        });  | 
 | 191 | +
  | 
 | 192 | +        setTimeout(() => ddtree.trigger("change"), 50);  | 
 | 193 | +      }  | 
 | 194 | +
  | 
 | 195 | +      // Function to create and insert a custom checkbox  | 
 | 196 | +      function createCustomCheckbox(ddtree) {  | 
 | 197 | +        const customCheckboxHtml = `  | 
 | 198 | +        <div class="k-check-all custom-check-all" style="padding: 8px; border-bottom: 1px solid #ddd;">  | 
 | 199 | +          <span class="k-checkbox-wrap">  | 
 | 200 | +            <input type="checkbox" id="checkAllCustom" class="k-checkbox-lg k-rounded-md k-checkbox">  | 
 | 201 | +            <label for="checkAllCustom" class="k-checkbox-label" style="margin-left: 4px;">Check All Custom</label>  | 
 | 202 | +          </span>  | 
 | 203 | +        </div>  | 
 | 204 | +      `;  | 
 | 205 | +
  | 
 | 206 | +        $(".custom-check-all").remove();  | 
 | 207 | +
  | 
 | 208 | +        const filterElement = ddtree.popup.element.find(".k-list-filter");  | 
 | 209 | +        if (filterElement.length > 0) {  | 
 | 210 | +          $(customCheckboxHtml).insertAfter(filterElement);  | 
 | 211 | +        } else {  | 
 | 212 | +          ddtree.popup.element.prepend(customCheckboxHtml);  | 
 | 213 | +        }  | 
 | 214 | +
  | 
 | 215 | +        $("#checkAllCustom")  | 
 | 216 | +          .off("change")  | 
 | 217 | +          .on("change", function () {  | 
 | 218 | +            handleCustomCheckAll(ddtree, $(this).is(":checked"));  | 
 | 219 | +          });  | 
 | 220 | +      }  | 
 | 221 | +
  | 
 | 222 | +      $("#dropdowntree").kendoDropDownTree({  | 
 | 223 | +        autoClose: false,  | 
 | 224 | +        open: function (e) {  | 
 | 225 | +          setTimeout(() => createCustomCheckbox(e.sender), 50);  | 
 | 226 | +        },  | 
 | 227 | +
  | 
 | 228 | +        filtering: function (e) {  | 
 | 229 | +          const ddtree = e.sender;  | 
 | 230 | +          saveCheckedStates(ddtree);  | 
 | 231 | +          setTimeout(() => {  | 
 | 232 | +            createCustomCheckbox(ddtree);  | 
 | 233 | +          }, 50);  | 
 | 234 | +        },  | 
 | 235 | +
  | 
 | 236 | +        dataBound: function (e) {  | 
 | 237 | +          const ddtree = e.sender;  | 
 | 238 | +          setTimeout(() => {  | 
 | 239 | +            if ($("#checkAllCustom").length > 0) {  | 
 | 240 | +            }  | 
 | 241 | +          }, 50);  | 
 | 242 | +        },  | 
 | 243 | +
  | 
 | 244 | +        check: function (e) {  | 
 | 245 | +          const ddtree = e.sender;  | 
 | 246 | +          const node = $(e.node);  | 
 | 247 | +          const dataItem = ddtree.treeview.dataItem(node);  | 
 | 248 | +          const checkbox = findCheckbox(node);  | 
 | 249 | +          const isChecked = checkbox.is(":checked");  | 
 | 250 | +
  | 
 | 251 | +          if (dataItem) {  | 
 | 252 | +            if (isChecked) {  | 
 | 253 | +              checkedStates.add(dataItem.text);  | 
 | 254 | +            } else {  | 
 | 255 | +              checkedStates.delete(dataItem.text);  | 
 | 256 | +            }  | 
 | 257 | +          }  | 
 | 258 | +        },  | 
 | 259 | +
  | 
 | 260 | +        dataSource: [  | 
 | 261 | +          {  | 
 | 262 | +            text: "Bedroom",  | 
 | 263 | +            value: "bedroom",  | 
 | 264 | +            items: [  | 
 | 265 | +              { text: "Queen-size bed", value: "queen-size-bed" },  | 
 | 266 | +              { text: "Single bed", value: "single-bed" },  | 
 | 267 | +            ],  | 
 | 268 | +          },  | 
 | 269 | +          {  | 
 | 270 | +            text: "Furniture",  | 
 | 271 | +            value: "furniture",  | 
 | 272 | +            expanded: true,  | 
 | 273 | +            items: [  | 
 | 274 | +              { text: "Tables & Chairs", value: "tables-chairs" },  | 
 | 275 | +              { text: "Sofas", value: "sofas" },  | 
 | 276 | +              { text: "Occasional Furniture", value: "occasional-furniture" },  | 
 | 277 | +            ],  | 
 | 278 | +          },  | 
 | 279 | +          {  | 
 | 280 | +            text: "Decor",  | 
 | 281 | +            value: "decor",  | 
 | 282 | +            items: [  | 
 | 283 | +              { text: "Bed Linen", value: "bed-linen" },  | 
 | 284 | +              { text: "Curtains & Blinds", value: "curtains-blinds" },  | 
 | 285 | +              { text: "Carpets", value: "carpets" },  | 
 | 286 | +            ],  | 
 | 287 | +          },  | 
 | 288 | +        ],  | 
 | 289 | +        checkboxes: true,  | 
 | 290 | +        checkAll: false,  | 
 | 291 | +        filter: "contains",  | 
 | 292 | +      });  | 
 | 293 | +    </script>  | 
 | 294 | +    <style>  | 
 | 295 | +      body {  | 
 | 296 | +        font-family: Helvetica, Arial, sans-serif;  | 
 | 297 | +        font-size: 14px;  | 
 | 298 | +      }  | 
 | 299 | +
  | 
 | 300 | +      .custom-check-all {  | 
 | 301 | +        background-color: #f8f9fa;  | 
 | 302 | +        border-bottom: 1px solid #dee2e6;  | 
 | 303 | +        position: sticky;  | 
 | 304 | +        top: 0;  | 
 | 305 | +        z-index: 10;  | 
 | 306 | +      }  | 
 | 307 | +
  | 
 | 308 | +      .custom-check-all .k-checkbox-wrap {  | 
 | 309 | +        display: flex;  | 
 | 310 | +        align-items: center;  | 
 | 311 | +      }  | 
 | 312 | +
  | 
 | 313 | +      .custom-check-all .k-checkbox-label {  | 
 | 314 | +        font-weight: 600;  | 
 | 315 | +        color: #495057;  | 
 | 316 | +        cursor: pointer;  | 
 | 317 | +      }  | 
 | 318 | +
  | 
 | 319 | +      .custom-check-all:hover {  | 
 | 320 | +        background-color: #e9ecef;  | 
 | 321 | +      }  | 
 | 322 | +
  | 
 | 323 | +      .custom-check-all .k-checkbox {  | 
 | 324 | +        margin-right: 8px;  | 
 | 325 | +      }  | 
 | 326 | +    </style>  | 
 | 327 | +```  | 
 | 328 | + | 
 | 329 | +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.  | 
 | 330 | + | 
 | 331 | +## See Also  | 
 | 332 | + | 
 | 333 | +- [Kendo UI for jQuery DropDownTree Overview](https://www.telerik.com/kendo-jquery-ui/documentation/controls/dropdowntree/overview)  | 
 | 334 | +- [Kendo UI for jQuery DropDownTree Checkboxes](https://www.telerik.com/kendo-jquery-ui/documentation/controls/dropdowntree/checkboxes)  | 
 | 335 | +- [JavaScript API Reference of the DropDownTree](https://www.telerik.com/kendo-jquery-ui/documentation/api/javascript/ui/dropdowntree)  | 
0 commit comments