|
| 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