如何使用角度材质树以角度6保存已检查的节点?

问题描述 投票:2回答:1

我正在使用角度6,我有两个组件,一个是主要组件,另一个是对话框,我有一个按钮,打开一个带有树的对话框。树节点有一个复选框!我有一个我要关闭的按钮,并在按下时保存已检查的项目。关闭对话框时我不知道如何控制项目!我在main.component.ts中使用对话框组件!这是代码:

main.component.ts

export interface DialogData {
  role_name: string;
  description: string;
  permission: string[];
}

export class TodoItemNode {
  children: TodoItemNode[];
  item: string;
}

/** Flat to-do item node with expandable and level information */
export class TodoItemFlatNode {
  item: string;
  level: number;
  expandable: boolean;
}

const TREE_DATA = {
  'Dashboard': null,
  'Reports': null,
  'Settings': {
    'Station Management': {
      'Station': null,
      'Work Shift': null,
      'Fuel Price': null,
      'Tank Management': null
    },
    'User Management': {
      'Users': null,
      'Groups': null
    },
    'Assets': {
      'Dispensers': null,
      'Tank Monitor': null
    },
    'Security': {
      'Admin Roles': null
    }
  }
};

@Injectable()
export class ChecklistDatabase {
  dataChange: BehaviorSubject<TodoItemNode[]> = new BehaviorSubject<TodoItemNode[]>([]);

  get data(): TodoItemNode[] { return this.dataChange.value; }

  constructor() {
    this.initialize();
  }

  initialize() {
    // Build the tree nodes from Json object. The result is a list of `TodoItemNode` with nested
    //     file node as children.
    const data = this.buildFileTree(TREE_DATA, 0);

    // Notify the change.
    this.dataChange.next(data);
  }

  buildFileTree(value: any, level: number) {
    const data: any[] = [];
    // tslint:disable-next-line:forin
    for (const k in value) {
      const v = value[k];
      const node = new TodoItemNode();
      node.item = `${k}`;
      if (v === null || v === undefined) {
        // no action
      } else if (typeof v === 'object') {
        node.children = this.buildFileTree(v, level + 1);
      } else {
        node.item = v;
      }
      data.push(node);
    }
    return data;
  }

  insertItem(parent: TodoItemNode, name: string) {
    const child = <TodoItemNode>{item: name};
    if (parent.children) {
      parent.children.push(child);
      this.dataChange.next(this.data);
    }
  }

  updateItem(node: TodoItemNode, name: string) {
    node.item = name;
    this.dataChange.next(this.data);
  }
}

//////////// Admin roles component where we did CRUD functions!
@Component({
  selector: 'app-admin-roles',
  templateUrl: './admin-roles.component.html',
  styleUrls: ['./admin-roles.component.css']
})
export class MainComponent implements OnInit {

  displayedColumns = ['role_name', 'description', 'permissions', 'actions'];
  dataSource;
  adminRoles;
  role_name: string;
  description: string;
  permission:string[];

  constructor(public dialog: MatDialog, private adminRoleService: AdminRolesService) { }

  ngOnInit() {

  }

  openPermissionDialog(role?) {
    console.log(role);
    const dialogRef = this.dialog.open(DialogPermissionComponent, {
      width: '640px',
      disableClose: true,
      data: { role_name: role ? role.role_name:this.role_name, description: role? role.description:this.description, permission: role? role.permission:this.permission }
    });
    dialogRef.afterClosed().subscribe(result => {
      console.log(result);
    })
  }

////////////

//////////// permission component where we set permissions
@Component({
  selector: 'app-dialog-content-example-dialog',
  templateUrl: './permission/dialog-permission-dialog.html',
  styleUrls: ['./permission/dialog-permission-dialog.css'],
  providers: [ChecklistDatabase]
})
export class DialogPermissionComponent {
  /** Map from flat node to nested node. This helps us finding the nested node to be modified */
  flatNodeMap: Map<TodoItemFlatNode, TodoItemNode> = new Map<TodoItemFlatNode, TodoItemNode>();

  /** Map from nested node to flattened node. This helps us to keep the same object for selection */
  nestedNodeMap: Map<TodoItemNode, TodoItemFlatNode> = new Map<TodoItemNode, TodoItemFlatNode>();

  /** A selected parent node to be inserted */
  selectedParent: TodoItemFlatNode | null = null;

  /** The new item's name */
  newItemName = '';

  treeControl: FlatTreeControl<TodoItemFlatNode>;

  treeFlattener: MatTreeFlattener<TodoItemNode, TodoItemFlatNode>;

  dataSource: MatTreeFlatDataSource<TodoItemNode, TodoItemFlatNode>;

  /** The selection for checklist */
  checklistSelection = new SelectionModel<TodoItemFlatNode>(true /* multiple */);

  constructor(private database: ChecklistDatabase, public dialogRef: MatDialogRef<DialogPermissionComponent>, @Inject(MAT_DIALOG_DATA) public data1: DialogData) {
    this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel,
      this.isExpandable, this.getChildren);
    this.treeControl = new FlatTreeControl<TodoItemFlatNode>(this.getLevel, this.isExpandable);
    this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

    database.dataChange.subscribe(data => {
      this.dataSource.data = data;
    });
  }

  getLevel = (node: TodoItemFlatNode) => node.level;

  isExpandable = (node: TodoItemFlatNode) => node.expandable;

  getChildren = (node: TodoItemNode): Observable<TodoItemNode[]> => {
    return ofObservable(node.children);
  }

  hasChild = (_: number, _nodeData: TodoItemFlatNode) => _nodeData.expandable;

  hasNoContent = (_: number, _nodeData: TodoItemFlatNode) => _nodeData.item === '';



  transformer = (node: TodoItemNode, level: number) => {
    // tslint:disable-next-line:no-non-null-assertion
    const flatNode = this.nestedNodeMap.has(node) && this.nestedNodeMap.get(node)!.item === node.item
      // tslint:disable-next-line:no-non-null-assertion
      ? this.nestedNodeMap.get(node)!
      : new TodoItemFlatNode();
    flatNode.item = node.item;
    flatNode.level = level;
    flatNode.expandable = !!node.children;
    this.flatNodeMap.set(flatNode, node);
    this.nestedNodeMap.set(node, flatNode);
    return flatNode;
  }

  /** Whether all the descendants of the node are selected */
  descendantsAllSelected(node: TodoItemFlatNode): boolean {
    const descendants = this.treeControl.getDescendants(node);
    return descendants.every(child => this.checklistSelection.isSelected(child));
  }

  /** Whether part of the descendants are selected */
  descendantsPartiallySelected(node: TodoItemFlatNode): boolean {
    const descendants = this.treeControl.getDescendants(node);
    const result = descendants.some(child => this.checklistSelection.isSelected(child));
    return result && !this.descendantsAllSelected(node);
  }


  todoItemSelectionToggle(node: TodoItemFlatNode): void {
    this.checklistSelection.toggle(node);
    const descendants = this.treeControl.getDescendants(node);
    this.checklistSelection.isSelected(node)
      ? this.checklistSelection.select(...descendants)
      : this.checklistSelection.deselect(...descendants);
  }

  OnClose() {
    this.dialogRef.close();
  }

}
/////////////

main.component.html:

<button mat-button-sm (click)="openPermissionDialog()" mat-icon-button aria-label="Open card menu">

dialog.html

    <mat-dialog-content>
    <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" >
      <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle matTreeNodePadding >
        <button mat-icon-button disabled></button>
        <mat-checkbox class="checklist-leaf-node"
                      [checked]="checklistSelection.isSelected(node)"
                      (change)="checklistSelection.toggle(node);">{{node.item}}</mat-checkbox>
      </mat-tree-node>

      <mat-tree-node *matTreeNodeDef="let node; when: hasNoContent" matTreeNodePadding>
        <button mat-icon-button disabled></button>
      </mat-tree-node>

      <mat-tree-node *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding>
        <button mat-icon-button matTreeNodeToggle
                [attr.aria-label]="'toggle ' + node.filename">
          <mat-icon class="mat-icon-rtl-mirror">
            {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
          </mat-icon>
        </button>
        <mat-checkbox [checked]="descendantsAllSelected(node)"
                      [indeterminate]="descendantsPartiallySelected(node)"
                      (change)="todoItemSelectionToggle(node)">{{node.item}}</mat-checkbox>
      </mat-tree-node>
    </mat-tree>
</mat-dialog-content>
<mat-dialog-actions>
  <button class="mat-button" mat-button (click)="OnClose()">Cancel</button>
  <button class="mat-button" mat-button [mat-dialog-close]="data1" cdkFocusInitial color="primary">Create</button>
</mat-dialog-actions>
typescript tree modal-dialog angular6 angular-material-6
1个回答
1
投票

我有同样的情况,一个带有mat-tree的对话框组件,我不得不保存已检查的项目;我发现所有选择都存储在名为'checklistSelection'的MatSelection对象中,您也可以在DialogPermissionComponent的代码中看到

checklistSelection = new SelectionModel<TodoItemFlatNode>(true /* multiple */);

在此结构中,您将找到所有已检查的节点及其子节点。

最好的祝福。

© www.soinside.com 2019 - 2024. All rights reserved.