Search code examples
angularangular-materialtreeviewangular-material-table

Angular Material Tree - Checkbox changes are not reflected on ngmodel


Checkbox changes are not reflected on ngmodel.

  1. Changing the data doesnt update the template: (checkbox changes - see the example)
  2. The only solution for moment to reload the datasource.data that will cause the tree to be collapsed all.
  3. Im adding new data parent and nodes on every expand (thats my requirements)

https://stackblitz.com/edit/angular-table-tree-example-8ss7qq?file=app%2Ftable-basic-example.ts&file=app%2Ftable-basic-example.html

enter image description here


Solution

  • Modify the following code and give it a try

    1. I have replaced ngModel with the checked attribute.
    2. After clicking checked reassigned the expanded state of all the items.
    3. Modified the tempNodes storage logic.
    <mat-checkbox
      [checked]="row.Access"
      (click)="$event.stopPropagation()"
      (change)="onSelectionChanged($event, row, i, j)"
    >
    </mat-checkbox>
    
    constructor() {
      this.dataSource.data = TREE_DATA;
      this.treeControl.expand(this.treeControl.dataNodes[0]);
    
      this.treeControl.dataNodes.forEach((node) =>
        this.tempNodes.push({
          ...node,
          expanded:
            this.treeControl.isExpanded(node) ||
            (node === this.treeControl.dataNodes[0] &&
              !this.treeControl.isExpanded(this.treeControl.dataNodes[0])),
        })
      );
    }
    
    logNode(clickedNode, index) {
      this.tempNodes = [];
      this.treeControl.dataNodes.forEach((node) =>
        this.tempNodes.push({
          ...node,
          expanded:
            this.treeControl.isExpanded(node) ||
            (node === clickedNode && !this.treeControl.isExpanded(clickedNode)),
        })
      );
    
      ... // Add the rest of the method code here
    }
    
    onSelectionChanged(arg: MatCheckboxChange, obj: any, i, j) {
      if (this.treeControl.isExpanded(obj)) {
        let parentObj;
    
        this.dataSource.data.forEach(
          (data) => (parentObj = this.findParentObj(obj, data))
        );
    
        this.checkAllsubNodes(obj, arg, i, j);
        parentObj.Access = arg.checked;
        this.dataSource.data = this.dataSource.data;
        this.setPreviousState();
      }
    }
    
    // Add the following methods
    
    findParentObj(obj, data) {
      if (obj.CategoryID === data.CategoryID && obj.FolderName === data.FolderName) {
        return data;
      } else if (data.subFolder?.length) {
        let sourceData = null;
        data.subFolder.forEach((row) => {
          const temp = this.findParentObj(obj, row);
          if (temp) {
            sourceData = temp;
          }
        });
        return sourceData;
      } else {
        return null;
      }
    }