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