0

I have a tree structure shamelessly acquired from building a treeview in aurelia

This works great when I push nodes onto the tree. What I would like to do is parse a json object and push that onto the tree. This partly works, as the tree is rendered but I am unable to expand / collapse nodes that have children. I believe this is due to a call to hasChildren being a method and not a property and possibly deep binding. I have tried changing this method to a get property but don't seem to be able to get this to work.

Node Model Class

export class NodeModel {
    public name: string;
    public visible: boolean;
    public children: NodeModel[];
    public expanded: boolean;
    public icon: string;    

    constructor(name: string, children: NodeModel[])
    {
        this.name = name;
        this.children = children || [];
        this.visible = true;

        if (this.hasChildren()) {
            this.icon = "fa fa-chevron-down";
            this.expanded = true;
        }
    }

    hasChildren(): boolean {
        return this.children.length > 0;
    }

    toggleNode(): void {

        for (var i: number = 0; i < this.children.length; i++) {
            this.children[i].visible = !this.children[i].visible;
        }

        this.expanded = !this.expanded;

        if (this.expanded === true) {
            this.icon = "fa fa-chevron-down";
        } else {
            this.icon = "fa fa-chevron-right";
        }
    }
}

Treeview VM

import {NodeModel} from "node-model";

export class T {    
    private locations: NodeModel[];    

    constructor() {        
        this.locations = [];
        var texas = new NodeModel('Texas',
            [new NodeModel('Houston', []),
                new NodeModel('Austin', [])]);

        console.log(JSON.stringify(texas));

        this.locations = [texas];     
    }     

    addCardiff(): void {        
        var cardiff = new NodeModel('Cardiff',
            [new NodeModel('Cardiff Bay', [])]);
        this.locations.push(cardiff);
    }    

    addBristol(): void {
        var bristol = `{"name":"Bristol","children":
                        [{"name":"Easton","children":[],"visible":true},
                        {"name":"Eastville","children":[],"visible":true}],
                        "visible":true,"icon":"fa fa-chevron-down","expanded":true}`;

        var d = JSON.parse(bristol);
        this.locations.push(d);
    }
}

Tree node component

import {bindable} from 'aurelia-framework';

export class TreeNode {

    @bindable current = null;

}

Tree node component view

<template>
    <ul show.bind="current.visible" style="list-style-type: none;">
        <li>
            <div>
                <span if.bind="current.hasChildren()" click.trigger="current.toggleNode()" class="${current.icon}"></span>
                <span>${current.name}</span>
            </div>

            <tree-node repeat.for="node of current.children" current.bind="node"></tree-node>

        </li>
    </ul>
</template>

view

<template>    
    <require from="tree-node"></require>
    <tree-node repeat.for="node of locations" current.bind="node"></tree-node>
    <button click.trigger="addCardiff()" class="btn btn-default">Add Cardiff</button>         
    <button click.trigger="addBristol()" class="btn btn-default">Add Bristol</button>             
</template>

Output below

enter image description here

Any ideas would be greatly appreciated.

Regards

Mike

4
  • Could you provide a gist that demonstrates your issue? You can use this gist.run/?id=c32f322b1f56e6f0a83679512247af7b a base Commented Jun 20, 2016 at 14:39
  • here is the Gist gist.run/?id=342be3fcf43c2d698dfefb95bdd9e9b2 doesn't run, probably because it's typescript. Commented Jun 20, 2016 at 15:05
  • tree-node webcomponent is missing. Could you provide that? Just copy and paste, don't worry if it is typescript Commented Jun 20, 2016 at 15:34
  • @FabioLuz, Thank you for the response. I have updated the gist now. Commented Jun 21, 2016 at 8:27

1 Answer 1

1

The addBristol() method partially works because you are pushing a plain javascript object, not a NodeModel object. You have to convert the object and its children to a NodeModel object before pushing them onto the locations array. In this way, you will be able to call hasChildren().

Sign up to request clarification or add additional context in comments.

1 Comment

Are you suggesting that I use a reviver on the JSON.parse method?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.