Angular 如何使用crud操作从rest api创建角度材质中的树结构

Angular 如何使用crud操作从rest api创建角度材质中的树结构,angular,angular-material-6,Angular,Angular Material 6,我正在尝试构建章节主题树,其中章节将是y主节点,主题将是我的子节点。我试图建立它,但什么问题,我面临的是我不能编辑或删除任何节点,因为我无法找到那里的水平正确。 任何一个都可以与所有操作共享一个代码 export class TodoItemNode { chapterTopicId: number; topicName: string; topics: TodoItemNode[]; } /** Flat to-do item node with expandable an

我正在尝试构建章节主题树,其中章节将是y主节点,主题将是我的子节点。我试图建立它,但什么问题,我面临的是我不能编辑或删除任何节点,因为我无法找到那里的水平正确。 任何一个都可以与所有操作共享一个代码

   export class TodoItemNode {
  chapterTopicId: number;
  topicName: string;
  topics: TodoItemNode[];
}

/** Flat to-do item node with expandable and level information */
export class TodoItemFlatNode {
  chapterTopicId: number;
  topicName: string;
  level: number;
  expandable: boolean;
}
以下是主要代码:

export class ChapterTopicComponent implements OnInit {

  flatNodeMap = new Map<TodoItemFlatNode, TodoItemNode>();

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

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

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

  clientGrades: any = [];
  clientSubjects: any = [];
  data: any = [];
  selectedGrade: string;
  selectedSubject: number;
  /**Current user value */
  user = JSON.parse(localStorage.getItem('currentUser'));

  topicName:string;

  treeControl: FlatTreeControl<TodoItemFlatNode>;

  treeFlattener: MatTreeFlattener<TodoItemNode, TodoItemFlatNode>;

  dataSource: MatTreeFlatDataSource<TodoItemNode, TodoItemFlatNode>;
  dataChange = new BehaviorSubject<TodoItemNode[]>([]);

  constructor(public dialog: MatDialog, private backendService: BackendService) {
    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);
    this.dataChange.subscribe(data => {
      this.dataSource.data = data;
    });
  }

  ngOnInit() {
    this.getClientGrades();
    this.getClientSubjects();
  }

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

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

  getChildren = (node: TodoItemNode): TodoItemNode[] => node.topics;

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

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

  /**
   * Transformer to convert nested node to flat node. Record the nodes in maps for later use.
   */
  transformer = (node: TodoItemNode, level: number) => {
    const existingNode = this.nestedNodeMap.get(node);
    const flatNode = existingNode && existingNode.topicName === node.topicName
      ? existingNode
      : new TodoItemFlatNode();
    flatNode.chapterTopicId = node.chapterTopicId;
    flatNode.topicName = node.topicName;
    flatNode.level = level;
    flatNode.expandable = !!node.topics?.length;
    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);
  //   const descAllSelected = descendants.length > 0 && descendants.every(child => {
  //     return this.checklistSelection.isSelected(child);
  //   });
  //   return descAllSelected;
  // }

  // /** 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);
  // }

  // /** Toggle the to-do item selection. Select/deselect all the descendants 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);

  //   // Force update for the parent
  //   descendants.forEach(child => this.checklistSelection.isSelected(child));
  //   this.checkAllParentsSelection(node);
  // }

  // /** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
  // todoLeafItemSelectionToggle(node: TodoItemFlatNode): void {
  //   this.checklistSelection.toggle(node);
  //   this.checkAllParentsSelection(node);
  // }

  // /* Checks all the parents when a leaf node is selected/unselected */
  // checkAllParentsSelection(node: TodoItemFlatNode): void {
  //   let parent: TodoItemFlatNode | null = this.getParentNode(node);
  //   while (parent) {
  //     this.checkRootNodeSelection(parent);
  //     parent = this.getParentNode(parent);
  //   }
  // }

  // /** Check root node checked state and change it accordingly */
  // checkRootNodeSelection(node: TodoItemFlatNode): void {
  //   const nodeSelected = this.checklistSelection.isSelected(node);
  //   const descendants = this.treeControl.getDescendants(node);
  //   const descAllSelected = descendants.length > 0 && descendants.every(child => {
  //     return this.checklistSelection.isSelected(child);
  //   });
  //   if (nodeSelected && !descAllSelected) {
  //     this.checklistSelection.deselect(node);
  //   } else if (!nodeSelected && descAllSelected) {
  //     this.checklistSelection.select(node);
  //   }
  // }

  /* Get the parent node of a node */
  getParentNode(node: TodoItemFlatNode): TodoItemFlatNode | null {
    const currentLevel = this.getLevel(node);

    if (currentLevel < 1) {
      return null;
    }

    const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;

    for (let i = startIndex; i >= 0; i--) {
      const currentNode = this.treeControl.dataNodes[i];

      if (this.getLevel(currentNode) < currentLevel) {
        return currentNode;
      }
    }
    return null;
  }

  /** Get client grades */
  getClientGrades() {
    this.backendService.getClientGrades(this.user.clientId, this.getCurrentYear()).subscribe(data => {
      this.clientGrades = data;
    });
  }

  /** Get client subjects */
  getClientSubjects() {
    this.backendService.getClientSubjects(this.user.clientId).subscribe(data => {
      this.clientSubjects = data;
    });
  }

  /** Get selected grade */
  onGradeSelection(grade: string) {
    this.selectedGrade = grade;
    if (this.selectedGrade != null && this.selectedSubject != null) {
      this.loadData(this.selectedGrade, this.selectedSubject);
    }
  }

  /** Get selected subject */
  onSubjectSelection(subject: number) {
    this.selectedSubject = subject;
    if (this.selectedGrade != null && this.selectedSubject != null) {
      this.loadData(this.selectedGrade, this.selectedSubject);
    }
  }
  /** Load chapter and topic of selected grade and selected subject */
  loadData(grade: string, subjectId: number) {
    this.backendService.getClientChapterTopics(this.user.clientId, grade, subjectId).subscribe(res => {
      this.data = res;
      this.dataChange.next(this.data);

    });

  }

  /** Get current year */
  getCurrentYear() {
    return new Date().getFullYear();
  }

  /** Refresh grade and subject */
  RefreshGradeSubject() {
    this.getClientGrades();
    this.getClientSubjects();
  }

  /** Add an item to to-do list */
  insertItem(parent: TodoItemNode, name: string) {
    if (parent.topics) {
      parent.topics.push({ topicName: name } as TodoItemNode);
      this.dataChange.next(this.data);
    }
  }

  updateItem(node: TodoItemNode, name: string) {
    if (name.length > 0) {
      node.topicName = name;
      this.dataChange.next(this.data);
    }
  }

  /** Select the category so we can insert the new item. */
  addNewItem(node: TodoItemFlatNode) {
    const parentNode = this.flatNodeMap.get(node);
    this.insertItem(parentNode!, '');
    this.treeControl.expand(node);
  }

  /** Save the node to database */
  saveNode(node: TodoItemFlatNode, itemValue: string) {
    if (itemValue.length > 0) {
      let parentNode = this.getParentNode(node);
      this.backendService.postTopic(itemValue,this.selectedSubject, this.selectedGrade, parentNode.chapterTopicId, this.user.clientId)
        .subscribe(response => {
          const nestedNode = this.flatNodeMap.get(node);
          this.updateItem(nestedNode!, itemValue);
          console.log(response);
        }, (error: string) => {
          console.log("error" + error);
        });

    }
  }
  findPosition(id: number, data: TodoItemNode[]) {
    for (let i = 0; i < data.length; i += 1) {
      
      if (id === data[i].chapterTopicId) {
        return i;
      }
    }
  }

  /** Edit node */
  editNode(node: TodoItemFlatNode){
    let parentNode = this.getParentNode(node);
    let topicName = this.openDialog();
    if(topicName.length>0){
    if(parentNode===null){
      this.backendService.putChapter(topicName, this.selectedSubject, this.selectedGrade, this.user.clientId).subscribe(response =>{
        node.topicName = this.topicName;
        this.dataChange.next(this.data);
      });
    }else{
      this.backendService.putTopic(topicName, this.selectedSubject, this.selectedGrade, parentNode.chapterTopicId, this.user.clientId).subscribe(response =>{
        node.topicName= this.topicName;
        this.dataChange.next(this.data);
      });
    }
  }
  }

  openDialog() {
    let topic:string;
    const dialogRef = this.dialog.open(AddChapterDialogComponent, {
      width: '300px',
      data:{topicName: this.topicName}
    });

    dialogRef.afterClosed().subscribe(result =>{
      topic = result;
    }); 
    return topic;
  }

}
导出类ChapterTopicComponent实现OnInit{
flatNodeMap=新映射();
/**从嵌套节点映射到展平节点。这有助于我们保留相同的对象以供选择*/
nestedNodeMap=新映射();
/**要插入的选定父节点*/
selectedParent:TodoItemFlatNode | null=null;
/**新项目的名称*/
newItemName='';
客户等级:任意=[];
客户主题:任意=[];
数据:any=[];
selectedGrade:字符串;
所选主题:编号;
/**当前用户值*/
user=JSON.parse(localStorage.getItem('currentUser');
主题名称:字符串;
treeControl:FlatTreeControl;
树展平机:马特里展平机;
数据源:MatTreeFlatDataSource;
dataChange=新的行为主体([]);
构造函数(公共对话框:MatDialog,私有后端服务:后端服务){
this.treeFlattener=新的MattreeFlatter(this.transformer,this.getLevel,
this.isExpandable,this.getChildren);
this.treeControl=新的FlatTreeControl(this.getLevel,this.isExpandable);
this.dataSource=新MatTreeFlatDataSource(this.treeControl,this.treeFlattener);
this.dataChange.subscribe(数据=>{
this.dataSource.data=数据;
});
}
恩戈尼尼特(){
这个.getClientGrades();
这是.getClientSubjects();
}
getLevel=(节点:TodoItemFlatNode)=>node.level;
isExpandable=(节点:TodoItemFlatNode)=>node.expandable;
getChildren=(节点:TodoItemNode):TodoItemNode[]=>node.topics;
hasChild=(\u:number,\u nodeData:TodoItemFlatNode)=>\u nodeData.expandable;
hasNoContent=(\u:number,\u nodeData:TodoItemFlatNode)=>\u nodeData.topicName==”;
/**
*将嵌套节点转换为平面节点的转换器。在映射中记录节点以供以后使用。
*/
transformer=(节点:TodoItemNode,级别:number)=>{
const existingNode=this.nestedNodeMap.get(节点);
const flatNode=existingNode&&existingNode.topicName===node.topicName
?现有节点
:新建TodoItemFlatNode();
flatNode.chapterTopicId=node.chapterTopicId;
flatNode.topicName=node.topicName;
flatNode.level=级别;
flatNode.expandable=!!节点.主题?.长度;
此.flatNodeMap.set(flatNode,node);
this.nestedNodeMap.set(node,flatNode);
返回平面节点;
}
///**是否选择了节点的所有子代*/
//子体所有选定(节点:TodoItemFlatNode):布尔值{
//const substands=this.treeControl.getsubstands(节点);
//const descAllSelected=substands.length>0&&substands.every(child=>{
//返回此.checklistSelection.isSelected(子项);
//   });
//返回所选名称;
// }
///**是否选择了部分子体*/
//子体局部选中(节点:TodoItemFlatNode):布尔值{
//const substands=this.treeControl.getsubstands(节点);
//const result=subjects.some(child=>this.checklistSelection.isSelected(child));
//返回结果&&!this.degeneratsAllSelected(节点);
// }
///**切换待办事项选择。选择/取消选择所有子节点*/
//todoItemSelectionToggle(节点:TodoItemFlatNode):无效{
//this.checklistSelection.toggle(节点);
//const substands=this.treeControl.getsubstands(节点);
//this.checklistSelection.isSelected(节点)
//?此.checklistSelection.select(…子体)
//:this.checklistSelection.disselect(…子体);
////强制更新父级
//forEach(child=>this.checklistSelection.isSelected(child));
//此.checkAllParentsSelection(节点);
// }
///**切换叶待办事项选择。检查所有父项以查看它们是否已更改*/
//todoLeafItemSelectionToggle(节点:TodoItemFlatNode):无效{
//this.checklistSelection.toggle(节点);
//此.checkAllParentsSelection(节点);
// }
///*选中/取消选中叶节点时检查所有父节点*/
//checkAllParentsSelection(节点:TodoItemFlatNode):无效{
//让parent:TodoItemFlatNode | null=this.getParentNode(节点);
//while(家长){
//这是checkRootNodeSelection(父级);
//父节点=此.getParentNode(父节点);
//   }
// }
///**检查根节点已检查状态并相应更改*/
//checkRootNodeSelection(节点:TodoItemFlatNode):无效{
//const nodeSelected=this.checklistSelection.isSelected(节点);
//const substands=this.treeControl.getsubstands(节点);
//const descAllSelected=substands.length>0&&substands.every(child=>{
//返回此.checklistSelection.isSelected(子项);
//   });
//如果(节点已选定&!说明已选定){
//this.checklistSelection.deselect(节点);
//}否则如果(!nodeSelected&&descAllSelected){
//this.checklistSelection.select(节点);
//   }
// }
/*获取节点的父节点*/
getParentNode(节点:TodoItemFlatNode):TodoItemFlatNode | null{
const currentLevel=this.getLevel(节点);
如果(当前电平<1){
返回null;
}
const startIndex=this.treeControl.dataNodes.indexOf(node)-1;
对于(设i=startIndex;i>=0;i--){
const currentNode=this.treeControl.dataNodes[i];
if(this.getLevel(currentNode){
this.clientGrades=数据;
});
}
/**获取客户主题*/
getClientSubjects(){
this.backendService.getClientSubject