Tee Jay
Tee Jay

Reputation: 77

Treeview in angular 2 - Alternative for ng-include and passing entire object between components

I am trying to create a treeview in angular 2. It is a tree of textboxes with add and delete buttons. I got it running in Angular 1 but it seems way complicated in angular 2.

Angular 1 HTML code:

<script type="text/ng-template"  id="tree_item_renderer.html">
     <input type="text" ng-model="data.answer" placeholder="Answer" required/>
    <button ng-click="add(data)">Add node</button>
    <button ng-click="delete(data)" ng-show="data.nodes.length > 0">Delete nodes</button>
    <ul>
        <li ng-repeat="data in data.nodes" ng-include="'tree_item_renderer.html'"></li>

    </ul>
</script>

<ul ng-app="Application" ng-controller="TreeController">
    <li ng-repeat="data in tree" ng-include="'tree_item_renderer.html'"></li>
</ul>

Javascript code:

angular.module("myApp", []).
controller("TreeController", ['$scope', function($scope) {
    $scope.delete = function(data) {
        data.nodes = [];
    };
    $scope.add = function(data) {
        data.nodes.push({answer:'',nodes: []});
    };
    $scope.tree = [{answer:'', nodes: []}];
}]);

Ng-include is not there in angular 2. So I tried to use @Input to pass data between the components. But new instance of the object gets created every time which overwrites the previous data!

Is there any way of tackling this in Angular 2?

Upvotes: 0

Views: 812

Answers (1)

Daniel Kucal
Daniel Kucal

Reputation: 9242

Assuming tree is a nested structure, in Angular2+ we can use component's tag in its template to achieve recursion:

export interface Tree {
    nodes: Tree;
}

@Component({
    selector: 'tree-view',
    template: `<ul><li *ngFor="let node of tree.nodes">
               <tree-view [tree]="node"></tree-view></li></ul>`
})
export class TreeViewComponent {
    @Input() public tree: Tree;
}

With your specific structure it will go this way:

export class TreeData {
    answer: string;
    child: TreeData[];

    constructor(answer: string, child: TreeData[]) {
        this.answer = answer;
        this.child = child;
    }
}

@Component({
    selector: 'tree-view',
    template: `<ul>
        <li *ngFor="let eachChild of tree; let i = index">
        <input type="text" [(ngModel)]="newAnswers[i]" placeholder="Answer" required>
        <button (click)="add(newAnswers[i], eachChild)">Add node</button>
        <tree-view [tree]="eachChild.child"></tree-view>
    </li></ul>`
})
export class TreeViewComponent {
    @Input() public tree: TreeData[];
    public newAnswers = Array<string> = [];

    public add(answer: string, node: TreeData) {
        node.child.push({answer, child: []});
    }
}

Upvotes: 2

Related Questions