title: Angular2: How to transform my tree model to fit a different interface?
body: <p>Suppose that I have an employee class that looks something like this: </p>
  
  <pre><code>export class Employee {
  
      jobTitle: string;
      firstName: string;
      lastName: string;
  
      boss: Employee;
      workers: Employee[];
  
      constructor(jobTitle: string, firstName: string, lastName: string){
          this.jobTitle = jobTitle;
          this.firstName = firstName;
          this.lastName = lastName;
      }
  
      public addWorker(worker: Employee){
          this.wokers.push(worker);
          worker.boss = this;
      }
  
  }
  </code></pre>
  
  <p>Suppose that we have initial <code>Employee</code>s that look something like this: </p>
  
  <pre><code>function getInitialStaff(): Employee {
  
      let headWaiter: Employee = new Employee( "Head Waiter", "Sarah", "Hilton" );
      headWaiter.addWorker(new Employee("Bus Boy", "Joe", "BeefEater"));
      headWaiter.addWorker(new Employee("Waiter", "Randy", "Rainman"));
  
      let headCheif: Employee = new Employee( "Head Cheif", "Phil", "Yorstomux" );
      headWaiter.addWorker(new Employee("Dishwasher", "Andy", "Shark"));
  
      let owner: Employee = new Employee( "Owner", "Boris", "Laughington" );
      owner.addWorker(headWaiter);
      owner.addWorker(headCheif);
      return owner;
  }
  </code></pre>
  
  <p>We can also assume that sometimes employees will be hired or fired.  Something along the lines of this:</p>
  
  <pre><code>window.setTimeout(()=&gt;{
      let someEmployee: Employee = /* Some existing employee */
      someEmployee.addWorker("someTitle", "someName", "someLastName");
  }, someAmountOfTime);
  </code></pre>
  
  <hr>
  
  <p>I want to display employees in a <a href="http://www.primefaces.org/primeng/#/tree" rel="noreferrer">PrimeNg tree</a>.  </p>
  
  <p>The tree widget requires that the data to be displayed conforms to the treeNode interface, which looks like this:</p>
  
  <pre><code>export interface TreeNode {
      label?: string;
      data?: any;
      icon?: any;
      expandedIcon?: any;
      collapsedIcon?: any;
      children?: TreeNode[];
      leaf?: boolean;
  }
  </code></pre>
  
  <p><strong>Main Question:</strong> Without changing my Employee class, what is the best way to transform the data into TreeNodes?  </p>
  
  <hr>
  
  <p>Things that I am thinking about: </p>
  
  <ul>
  <li>When I add a new Employee, I want to maintain my tree state (what is open, what is selected, etc)</li>
  <li>I need to be able to easily retrieve the employee that is currently selected.  </li>
  <li>I am trying to avoid maintaining two duplicate models.</li>
  <li>I want to take advantage of Angular2's change detection in a reasonable, but scalable way</li>
  </ul>
  
  <hr>
  
  <p>This is what my EmployeeTree component look like at the moment: </p>
  
  <pre><code>@Component({
      selector: 'employee-tree',
      template: `
          &lt;div&gt;
              &lt;p-tree&gt;
                  /* Open Question, I need to transform owner and then tie the resulting TreeNode to the tree */
              &lt;/p-tree&gt;
          &lt;/div&gt;
      `
      directives: [ Tree ]
  })
  export class EmployeeTree {
      @Input()
      private owner: Employee;
  }
  </code></pre>
  
  <hr>
  
  <p><strong>Option 1</strong> - Create a pipe that will transform an Employee into TreeNode</p>
  
  <p>I guess that would leave my template looking like this: </p>
  
  <pre><code>&lt;p-tree [value]="owner | convertToTreeNode"&gt;&lt;/p-tree&gt;
  </code></pre>
  
  <p>And I would create a pipe that did something like this: </p>
  
  <pre><code>@Pipe({name: 'convertToTreeNode'})
  export class ToTreeNode implements PipeTransform {
      transform(employee: Employee): TreeNode {
  
          let treeNode: TreeNode = {
              label: employee.firstName + " " + employee.lastName,
              data: employee,
              children: []
          };
  
          employee.workers.forEach(worker =&gt; {
              treeNode.children.push(this.transform(worker));
          })
  
          return treeNode;
  
      }
  }
  </code></pre>
  
  <p>Pros/Cons: </p>
  
  <ul>
  <li>This takes advantage of angular's change detection </li>
  <li>If this is a pure pipe, it may miss changes</li>
  <li>If this is an impure pipe, it may be too heavy</li>
  <li>Leaves the component very clean and delegates responsibility to the pipe</li>
  <li>Not sure if this will preserve my gui state (what is selected and what is open/closed) when a new item is added</li>
  </ul>
  
  <hr>
  
  <p><strong>Option 2</strong> - Inside the component maintain a separate structure for the tree</p>
  
  <pre><code>@Component({
      selector: 'employee-tree',
      template: `
          &lt;div&gt;
              &lt;p-tree [data]="employeeTree"&gt;
              &lt;/p-tree&gt;
          &lt;/div&gt;
      `
      directives: [ Tree ]
  })
  export class EmployeeTree {
      @Input()
      private owner: Employee;
  
      private employeeTree: TreeNode;
  
      // TODO - Somehow watch the owner for changes (how?) and then repopulate the employeeTree
  }
  </code></pre>
  
  <p>I think that I could make the Employee emit an event that trickles up when it changes.  This could give me something to hook into.  </p>
  
  <hr>
  
  <p>Generally speaking, what is the best way to use Angular2 to do something like this.  </p>
  
  <p>To summarize, I want to use a widget that expects data in a <em>slightly</em> different format than what I am storing it in.  What is the standard angular2 way to massage my data into the widget?  Is there special angular2 sauce that will help me here?  Should I maintain two separate models?  Potentially my tree could have 100s or possibly 1000s of items in it, so I am somewhat concerned with performance.  </p>