Abdel Posada
Abdel Posada

Reputation: 47

Generate nested structure for dynamic data for angular

I'm having a problem trying to generate a dynamic structure. I have the following string.

"Client->Plant->Route->Turn"

I have a list of devices that has a value on every field on this string and additional data, like this

[
  {
    "Client": "Client 1",
    "Plant": "Plant 1",
    "Route": "Route 1",
    "Turn": "Turn 1",
    "ascends": 10,
    "descends": 5,
    "deviceId": 1
  },
  {
    "Client": "Client 1",
    "Plant": "Plant 1",
    "Route": "Route 2",
    "Turn": "Turn 1",
    "ascends": 10,
    "descends": 5,
    "deviceId": 2
  },
  {
    "Client": "Client 1",
    "Plant": "Plant 1",
    "Route": "Route 3",
    "Turn": "Turn 1",
    "ascends": 10,
    "descends": 5,
    "deviceId": 3
  },
  {
    "Client": "Client 1",
    "Plant": "Plant 2",
    "Route": "Route 1",
    "Turn": "Turn 1",
    "ascends": 10,
    "descends": 5,
    "deviceId": 4
  },
  {
    "Client": "Client 1",
    "Plant": "Plant 1",
    "Route": "Route 3",
    "Turn": "Turn 4",
    "ascends": 10,
    "descends": 5,
    "deviceId": 5
  },
  {
    "Client": "Client 2",
    "Plant": "Plant 1",
    "Route": "Route 1",
    "Turn": "Turn 1",
    "ascends": 10,
    "descends": 5,
    "deviceId": 6
  }
]

I need to show this info in a dynamic bootstrap collpase

Client 1            
    Plant 1     
        Route 1 
            Turn 1
        Route 2 
            Turn 1
        Route 3 
            Turn 1
            Turn 4
    Plant 2     
        Route 1 
            Turn 1
Client 2            
    Plant 1     
        Route 1 
            Turn 1

I don't need to use idents in the collapse component, is just for make it more understandable.

I'm using angular 6, so I was searching components and I found one that allows you to generate "n" nested lists. https://gist.github.com/arniebradfo/5cf89c362cc216df6fc1d9ca4d536b72

Here is an example of how should it look

[
  {
    "title": "Client 1",
    "children": [
      {
        "title": "Plant 1",
        "children": [
          {
            "title": "Route 1",
            "children": [
              {
                "title": "Turn 1",
                "ascends": 10,
                "descends": 5,
                "deviceId": 1
              }
            ]
          },
          {
            "title": "Route 2",
            "children": [
              {
                "title": "Turn 1",
                "ascends": 10,
                "descends": 5,
                "deviceId": 2
              }
            ]
          },
          {
            "title": "Route 3",
            "children": [
              {
                "title": "Turn 1",
                "ascends": 10,
                "descends": 5,
                "deviceId": 3
              },
              {
                "title": "Turn 4",
                "ascends": 10,
                "descends": 5,
                "deviceId": 5
              }
            ]
          }
        ]
      },
      {
        "title": "Plant 2",
        "children": [
          {
            "title": "Route 1",
            "children": [
              {
                "title": "Turn 1",
                "ascends": 10,
                "descends": 5,
                "deviceId": 4
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "title": "Client 2",
    "children": [
      {
        "title": "Plant 1",
        "children": [
          {
            "title": "Route 1",
            "children": [
              {
                "title": "Turn 1",
                "ascends": 10,
                "descends": 5,
                "deviceId": 6
              }
            ]
          }
        ]
      }
    ]
  }
]

The first string that I put CAN CHANGE, so can be more items and have different order, that's why I need to make it dynamic.

I want to create an array like the component one example for display my data.

Also in the last level it must show the "additional data".

Thanks.

Upvotes: 1

Views: 349

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386512

You could take an array for the keys for nesting the items and reduce the given data by reducing the keys and creating neede objects. Finally push the data at at the most nested array.

This approach uses rest properties for objects.

var data = [{ Client: "Client 1", Plant: "Plant 1", Route: "Route 1", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 1 }, { Client: "Client 1", Plant: "Plant 1", Route: "Route 2", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 2 }, { Client: "Client 1", Plant: "Plant 1", Route: "Route 3", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 3 }, { Client: "Client 1", Plant: "Plant 2", Route: "Route 1", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 4 }, { Client: "Client 1", Plant: "Plant 1", Route: "Route 3", Turn: "Turn 4", ascends: 10, descends: 5, deviceId: 5 }, { Client: "Client 2", Plant: "Plant 1", Route: "Route 1", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 6 }],
    keys = ['Client', 'Plant', 'Route'],
    tree = data.reduce((r, { Turn, ascends, descends, deviceId, ...o }) => {
        keys
            .reduce((s, k) => {
                var temp = s.find(({ title }) => title === o[k]);
                if (!temp) {
                    s.push(temp = { title: o[k], children: [] });
                }
                return temp.children;
            }, r)
            .push({ title: Turn, ascends, descends, deviceId });
        return r;
    }, []);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

A differetn approach wich takes all properties dynamically by using an array of the keys for nesting.

var data = [{ Client: "Client 1", Plant: "Plant 1", Route: "Route 1", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 1 }, { Client: "Client 1", Plant: "Plant 1", Route: "Route 2", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 2 }, { Client: "Client 1", Plant: "Plant 1", Route: "Route 3", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 3 }, { Client: "Client 1", Plant: "Plant 2", Route: "Route 1", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 4 }, { Client: "Client 1", Plant: "Plant 1", Route: "Route 3", Turn: "Turn 4", ascends: 10, descends: 5, deviceId: 5 }, { Client: "Client 2", Plant: "Plant 1", Route: "Route 1", Turn: "Turn 1", ascends: 10, descends: 5, deviceId: 6 }],
    keys = ['Client', 'Plant', 'Route', 'Turn'],
    tree = [];


data.reduce((r, o) => {
    var p = keys.reduce((s, k) => {
        s.children = s.children || [];
        var temp = s.children.find(({ title }) => title === o[k]);
        if (!temp) {
            s.children.push(temp = { title: o[k] });
        }
        return temp;
    }, r);
    Object
        .keys(o)
        .filter(k => !keys.includes(k))
        .forEach(k => p[k] = o[k]);
    return r;
}, { children: tree });

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions