Search code examples
javascriptangulartypescriptprimeng

How to convert JSON Data to Tree Structure Algorithm with PrimeNG Tree Interface in Angular


Good day I have the following data that I want to convert to tree structure algorithm and am using PrimeNG treeNode Interface.

export interface TreeNode {
    label?: string;
    data?: any;
    icon?: any;
    expandedIcon?: any;
    collapsedIcon?: any;
    children?: TreeNode[];
    leaf?: boolean;
    expanded?: boolean;
    type?: string;
    parent?: TreeNode;
    partialSelected?: boolean;
    styleClass?: string;
    draggable?: boolean;
    droppable?: boolean;
    selectable?: boolean;
    key?: string;
}

My Data from the API is in the following format:

"result": [

    {
      "permissionName": "Roles",
      "level": 2,
      "selectable": true,
      "children": [
        {
          "permissionName": "Roles.Create",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Roles.Edit",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Roles.Delete",
          "level": 3,
          "selectable": true,
          "children": []
        }
      ]
    },
     {
      "permissionName": "Users",
      "level": 2,
      "selectable": true,
      "children": [
        {
          "permissionName": "Users.Create",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Users.Edit",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Users.Delete",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Users.ChangePermissions",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Users.Impersonation",
          "level": 3,
          "selectable": true,
          "children": []
        },
        {
          "permissionName": "Users.Unlock",
          "level": 3,
          "selectable": true,
          "children": []
        }
      ]
    }
]

I have implemented the following but is not working for second level Children upward; this is my code:

let permissionResult = resultFromAPI;
      //  let childrenArray: TreeNode[] = [];
        for(var i= 0; i< permissionResult.permissions.length;i++){

            this.treeData.push({
            label:permissionResult.permissions[i].permissionName,
            icon: 'pi pi-folder',
            data:permissionResult.permissions[i].permissionName,
            children: this.childrenArrayfunction(permissionResult.permissions[i].children)
          })

          if (permissionResult.permissions[i].selected) {
            this.grantedPermissionNames.push(permissionResult.permissions[i].permissionName)
          }
        }

childrenArrayfunction(resultArray:any[]=[]){
    let childArray: TreeNode[]=[];
    if(resultArray.length > 0){
        for(var j= 0; j< resultArray.length;j++){
            childArray.push({
              label:resultArray[j].permissionName,
              data:resultArray[j].permissionName,
              icon: 'pi pi-folder',

            })
          }

    }

    return childArray;
  }

it is only working for the Parent Element and first Children, from second children upward, it does not work, is there any better way to do. Please help. Thank you


Solution

  • I modified basic demo from https://primeng.org/tree#api.properties

    Changes in service:

    • added interface:
    export interface DataNode {
        permissionName: string,
        level: number,
        selectable: boolean,
        children?: DataNode[],
    }
    
    
    • map function:
    dataToTreeNode(dataNodes?: DataNode[]): TreeNode<string>[] {
            return (dataNodes||[]).map(dataNode => {
                return {
                    label: dataNode.permissionName.split('.').at(-1),
                    selectable: dataNode.selectable,
                    children: this.dataToTreeNode(dataNode.children),
                };
            });
        }
    
    • get data function (I modified your data to get one more level):
    getTreeNodes1(): TreeNode[] {
        return this.dataToTreeNode(this.getDataNodes());
      }
    
      getDataNodes(): DataNode[] {
        return [
          {
            permissionName: 'Roles',
            level: 2,
            selectable: true,
            children: [
              {
                permissionName: 'Roles.Create',
                level: 3,
                selectable: true,
                children: [],
              },
              {
                permissionName: 'Roles.Edit',
                level: 3,
                selectable: true,
                children: [],
              },
              {
                permissionName: 'Roles.Delete',
                level: 3,
                selectable: true,
                children: [{
                  permissionName: 'Users.ChangePermissions',
                  level: 3,
                  selectable: true,
                  children: [],
                },
                {
                  permissionName: 'Users.Impersonation',
                  level: 3,
                  selectable: true,
                  children: [],
                },
                {
                  permissionName: 'Users.Unlock',
                  level: 3,
                  selectable: true,
                  children: [],
                },],
              },
            ],
          },
          {
            permissionName: 'Users',
            level: 2,
            selectable: true,
            children: [
              {
                permissionName: 'Users.Create',
                level: 3,
                selectable: true,
                children: [],
              },
              {
                permissionName: 'Users.Edit',
                level: 3,
                selectable: true,
                children: [],
              },
              {
                permissionName: 'Users.Delete',
                level: 3,
                selectable: true,
                children: [],
              },
              
            ],
          },
        ];
      }
    

    then use it to bind data:

    ngOnInit() {
      this.files = this.nodeService.getTreeNodes1();
    }
    

    And it works: enter image description here