1

Given the input data

+-------+---------+
| node  | subnode |
+-------+---------+
|   3   |    6    |
|   3   |    7    |
|   3   |    8    |
|   3   |    9    |
|   6   |    8    |
|   7   |    9    |
|   9   |    8    |
+-------+---------+

e.g. as a 2D array:

const tree = [
  [3, 6],
  [3, 7],
  [3, 8],
  [3, 9],
  [6, 8],
  [7, 9],
  [9, 8]
];

describing this tree:

3
├─ 6
│  └─ 8
├─ 7
│  └─ 9
│     └─ 8
├─ 8
└─ 9
   └─ 8

How to implement an Angular solution to show this on a web page let's say as nested <div>s like

<div id="node3" style="padding-left:2em">3<div id="node6" [...]</div>

? Illustration:

enter image description here

tom
  • 2,137
  • 2
  • 27
  • 51

1 Answers1

1

Günter Zöchbauer linked his solution which works well for simple cases where the tree view is "passive", so it is only to visualize some data as a static element.

However, if there should be communication between the tree in the template and the component (e.g. a node has a (click) event that calls a method defined in the component), due to the fact that Günter's solution uses recursively self-contained components each node having its own directive, one might face issues:

Handling the tree as a whole from the component is made difficult because of multiple scopes created by the repetition of the component. (- Correct me if I'm wrong.)

That's why I needed another solution which is template-only and this way not causing the component to be replicated for each node. Here it is:

In the .ts:

const nodes = [{
  number: 3,
  children: [{
    number: 6,
    children: [{
      number: 8,
      children: []
    }]
  }, {
    number: 7,
    children: [{
      number: 9,
      children: [{
        number: 8,
        children: []
      }]
    }]
  }, {
    number: 8,
    children: []
  }, {
    number: 9,
    children: [{
      number: 8,
      children: []
    }]
  }]
}];

In the .html:

<ng-template #recursion let-nodes>
  <div style="margin-left:2em" *ngFor="let node of nodes">
    {{node.number}}
    <ng-container *ngIf="node.children.length > 0">
      <ng-container *ngTemplateOutlet="recursion;
        context:{ $implicit: node.children }"></ng-container>
    </ng-container>
  </div>
</ng-template>
<ng-container *ngTemplateOutlet="recursion;
  context:{ $implicit: nodes }"></ng-container>

P.S.: See these answers on how to convert tree to nodes.

tom
  • 2,137
  • 2
  • 27
  • 51
  • 1
    With my approach, when you provide a shared service (with shared functionality and communication between the nodes) in a component that wraps the whole tree and inject it in every "node" component, you get probably quite a similar experience. – Günter Zöchbauer Dec 14 '17 at 20:45