Skip to content

Commit f456e85

Browse files
fabioloreggianjosephperrott
authored andcommitted
docs(tree-checklist-example): root tree node correct selected state (#13523)
1 parent 183df8f commit f456e85

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

src/material-examples/tree-checklist/tree-checklist-example.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<button mat-icon-button disabled></button>
44
<mat-checkbox class="checklist-leaf-node"
55
[checked]="checklistSelection.isSelected(node)"
6-
(change)="checklistSelection.toggle(node);">{{node.item}}</mat-checkbox>
6+
(change)="todoLeafItemSelectionToggle(node)">{{node.item}}</mat-checkbox>
77
</mat-tree-node>
88

99
<mat-tree-node *matTreeNodeDef="let node; when: hasNoContent" matTreeNodePadding>

src/material-examples/tree-checklist/tree-checklist-example.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,13 @@ export class TreeChecklistExample {
168168
return flatNode;
169169
}
170170

171-
/** Whether all the descendants of the node are selected */
171+
/** Whether all the descendants of the node are selected. */
172172
descendantsAllSelected(node: TodoItemFlatNode): boolean {
173173
const descendants = this.treeControl.getDescendants(node);
174-
return descendants.every(child => this.checklistSelection.isSelected(child));
174+
const descAllSelected = descendants.every(child =>
175+
this.checklistSelection.isSelected(child)
176+
);
177+
return descAllSelected;
175178
}
176179

177180
/** Whether part of the descendants are selected */
@@ -188,6 +191,61 @@ export class TreeChecklistExample {
188191
this.checklistSelection.isSelected(node)
189192
? this.checklistSelection.select(...descendants)
190193
: this.checklistSelection.deselect(...descendants);
194+
195+
// Force update for the parent
196+
descendants.every(child =>
197+
this.checklistSelection.isSelected(child)
198+
);
199+
this.checkAllParentsSelection(node);
200+
}
201+
202+
/** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
203+
todoLeafItemSelectionToggle(node: TodoItemFlatNode): void {
204+
this.checklistSelection.toggle(node);
205+
this.checkAllParentsSelection(node);
206+
}
207+
208+
/* Checks all the parents when a leaf node is selected/unselected */
209+
checkAllParentsSelection(node: TodoItemFlatNode): void {
210+
let parent: TodoItemFlatNode | null = this.getParentNode(node);
211+
while (parent) {
212+
this.checkRootNodeSelection(parent);
213+
parent = this.getParentNode(parent);
214+
}
215+
}
216+
217+
/** Check root node checked state and change it accordingly */
218+
checkRootNodeSelection(node: TodoItemFlatNode): void {
219+
const nodeSelected = this.checklistSelection.isSelected(node);
220+
const descendants = this.treeControl.getDescendants(node);
221+
const descAllSelected = descendants.every(child =>
222+
this.checklistSelection.isSelected(child)
223+
);
224+
if (nodeSelected && !descAllSelected) {
225+
this.checklistSelection.deselect(node);
226+
} else if (!nodeSelected && descAllSelected) {
227+
this.checklistSelection.select(node);
228+
}
229+
}
230+
231+
/* Get the parent node of a node */
232+
getParentNode(node: TodoItemFlatNode): TodoItemFlatNode | null {
233+
const currentLevel = this.getLevel(node);
234+
235+
if (currentLevel < 1) {
236+
return null;
237+
}
238+
239+
const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;
240+
241+
for (let i = startIndex; i >= 0; i--) {
242+
const currentNode = this.treeControl.dataNodes[i];
243+
244+
if (this.getLevel(currentNode) < currentLevel) {
245+
return currentNode;
246+
}
247+
}
248+
return null;
191249
}
192250

193251
/** Select the category so we can insert the new item. */

0 commit comments

Comments
 (0)