angular中如何将后端返回的多层嵌套json数据转换成树状层级结构

后端返回嵌套json数据的方法见我的另一篇博客:https://www.cnblogs.com/wwwzgy/p/15561613.html

返回的是一个多层嵌套式的json,示例格式如下,这是一个公司的部门架构,可以无限多层嵌套。

[
    {"id":"0000000001",
      "name":"总公司",
      "parent_id":"0",
      "operate_time":"2021-11-15 20:46:12",
      "children":[
                        {"id":"0100000000",
                          "name":"分公司1",
                          "parent_id":"0000000001",
                           "children":[
                                            {"id":"0101000000",
                                               "name":"部门1",
                                              "parent_id":"0100000000",
                                              "children":[]},
                                            {"id":"0102000000",
                                              "name":"部门2", 
                                              "parent_id":"0100000000",
                                              "children":[]}
                                            ]
                         },
                         {"id":"0200000000",
                            "name":"分公司2",
                            "parent_id":"0000000001",
                             "children":[]
                          }
                    ]
        }
]             

前端的展示效果如下图所示:

angular中如何将后端返回的多层嵌套json数据转换成树状层级结构

 前端的html页面,参考ant design给出的模板代码。仅改变其中一句:<a (click)="search(node.name)"> {{ node.name }}</a>

末尾是为了考虑本html页面在实际运用中是一个弹出框,所以增加了“取消”和“确定”两个按钮,以及为了获得后台数据的链接(根据实际情况,可改成自动获取数据)。 angular中如何将后端返回的多层嵌套json数据转换成树状层级结构
<div class="edituser-dialog">
    <nz-tree-view [nzTreeControl]="treeControl" [nzDataSource]="dataSource">
        <nz-tree-node *nzTreeNodeDef="let node" nzTreeNodePadding>
          <nz-tree-node-toggle nzTreeNodeNoopToggle></nz-tree-node-toggle>
          <nz-tree-node-option
            [nzDisabled]="node.disabled"
            
            (nzClick)="selectListSelection.toggle(node)"
          >
            <a (click)="search(node.name)">{{ node.name }}</a>
          </nz-tree-node-option>
        </nz-tree-node>
  
        <nz-tree-node *nzTreeNodeDef="let node; when: hasChild" nzTreeNodePadding>
          <nz-tree-node-toggle>
            <i nz-icon nzType="caret-down" nzTreeNodeToggleRotateIcon></i>
          </nz-tree-node-toggle>
          <nz-tree-node-option
            [nzDisabled]="node.disabled"
            
            (nzClick)="selectListSelection.toggle(node)"
          >
          <a (click)="search(node.name)"> {{ node.name }}</a>
          </nz-tree-node-option>
        </nz-tree-node>
    </nz-tree-view>
    
    <div><a (click)="getOrganization()">获取部门数据</a></div>

    <div class="edituser-dialog-footer">
      <button nz-button nzSize="large" style="margin-right: 10px;" [nzType]="'default'"
        (click)="handleCancel()">取消</button>
      <button nz-button nzSize="large" [nzType]="'primary'" (click)="handleConfirm()">确定</button>
    </div>
</div>
View Code

ts的代码,也是参考ant design给出的模板代码。增加getOrganization()方法以及transferData()方法,getOrganization()是获取后台是json数据,transferData()则是将json数据转换成前端要求的TreeNode类型数据,其中采用了递归的方法实现转换。

angular中如何将后端返回的多层嵌套json数据转换成树状层级结构
interface TreeNode {
  name: string;
  disabled?: boolean;
  children?: TreeNode[];
}

var TREE_DATA: TreeNode[] = [];

interface FlatNode {
  expandable: boolean;
  name: string;
  level: number;
  disabled: boolean;
}

@Component({
  selector: 'app-department',
  templateUrl: './department.component.html',
  styleUrls: ['./department.component.less'],
})
export class DepartmentComponent implements OnInit {

  ngOnInit(): void {
  }


  organizationTree: TreeNode[]=[];

  constructor(private http: HttpClient,private subject: NzModalRef,) {
    this.dataSource.setData(TREE_DATA);
    this.treeControl.expandAll();
  }

  private transformer = (node: TreeNode, level: number): FlatNode => ({
    expandable: !!node.children && node.children.length > 0,
    name: node.name,
    level,
    disabled: !!node.disabled
  });
  selectListSelection = new SelectionModel<FlatNode>(true);

  treeControl = new FlatTreeControl<FlatNode>(
    node => node.level,
    node => node.expandable
  );

  treeFlattener = new NzTreeFlattener(
    this.transformer,
    node => node.level,
    node => node.expandable,
    node => node.children
  );

  dataSource = new NzTreeFlatDataSource(this.treeControl, this.treeFlattener);

  hasChild = (_: number, node: FlatNode): boolean => node.expandable;

  search(name:string):void{
    console.log(name);
  }

  getOrganization():void{
    this.http.post("api/department", {
    responseType: "json",
    headers: new HttpHeaders().append("Content-Type", "application/json")
                              .append('Authorization', 'Bearer '+localStorage.getItem("token"))
    }).subscribe(       
        res=> { 
          console.log(res);
          this.transferData(res,this.items);
          TREE_DATA=this.items;
          this.dataSource.setData(TREE_DATA);          
        }
      );
  }
  items: TreeNode[]=[];
  transferData(jsonList:any,items:TreeNode[]):void{      
      for(let i=0; i<jsonList.length; i++){
        var node: TreeNode={name:"",disabled:false,children:[]};
        items.push(node);
        if(jsonList[i].children.length>0){
          this.transferData(jsonList[i].children,items[i].children);
        }
        items[i].name=jsonList[i].name;
      }
  }

  handleCancel():void{
    this.subject.destroy('onCancel');
  }
  handleConfirm():void{

  }
}
View Code

transferData()详解:

items: TreeNode[]=[];   //构造一个空数组,用于存放最终结果
  transferData(jsonList:any,items:TreeNode[]):void{      //jsonList就是后端返回的json数组
      for(let i=0; i<jsonList.length; i++){  //循环遍历后端返回的jsonList中的每个json数据
        var node: TreeNode={name:"",disabled:false,children:[]};  //构造一个空的TreeNode数据,此句必须放在循环体里
        items.push(node);
        if(jsonList[i].children.length>0){  //如果jsonList有下一层
          this.transferData(jsonList[i].children,items[i].children);  //递归找到下一层的json
        }
        items[i].name=jsonList[i].name;  //取出部门名字,根据需要也可以把部门id等信息取出
      }
  }

 

上一篇:JS中字符串拼接


下一篇:认识NgModule~Angular的模块化