0

I'm trying to make use of treant-js in an Angular2 project, and I'm struggling with how to properly integrate it.

I have a working vanilla JavaScript / HTML example that I'm trying to make work in Angular2.

I've created a component, added treant-js and raphael from npm, and imported them into the component.

import * as Raphael from 'raphael';
import * as Treant from 'treant-js';

I've setup the html template and the corresponding css to match the standalone javascript project.

<div class="tree-wrapper" >
    <div class="chart" id="test-tree"></div>
</div>

And in the class I'm defining the tree-structure variable

   private tree_structure: any = {
        chart: {
            container: "#test-tree",
            levelSeparation: 20,
            siblingSeparation: 15,
            subTeeSeparation: 15,
            rootOrientation: "WEST",

            node: {
                HTMLclass: "tree-wrapper",
                drawLineThrough: true
            },
            connectors: {
                type: "straight",
                style: {
                    "stroke-width": 2,
                    "stroke": "#ccc"
                }
            }
        },

        nodeStructure: {
            text: {
                name: { val: "Djokovic, Novak", href: "http://... }
            },
            HTMLclass: "animal",
            image: "flags/can.jpg",
            children: [...
   *** the rest of the object graph continues ***
}

In the JavaScript / HTML version, the tree is loaded in an inline script like this:

<script>
   new Treant( tree_structure );
</script>

What's the proper way to initialize this in Angular2?

I was thinking something like this:

private tree: Treant = new Treant();

ngOnInit() {
    tree ( this.tree_structure );
}

However Treant isn't a function.

I'm sure I'm missing something obvious here, but I can't wrap my head around this.

Stephen R. Smith
  • 3,310
  • 1
  • 25
  • 41

1 Answers1

3

The solution is as follows:

Import the scripts into the index.html file - don't add them via npm, just load the js files into wherever you store your static import assets, in this case I have an assets directory at the root of the project that contains static CSS files (BootStrap) and static images, as well as a js subdirectory that contains the Treant and Raphael files.

  <script src="/assets/js/raphael.js"></script>
  <script src="/assets/js/Treant.js"></script>

Then create a component, and turn off ViewEncapsulation so that the Treant CSS styles will work.

import { Component, Input } from '@angular/core';
import { ViewEncapsulation } from '@angular/core'

declare var Treant: any;

@Component({
    encapsulation: ViewEncapsulation.None,
    selector: 'treant-tree',
    styleUrls: ['treant-tree.component.scss'],
    template: `
<div class="treant-class" >
    <div class="chart" id="treant-id"></div>
</div>
  `
})
export class TreantTree {...}

I used the Tennis Example, so create the nodeStructure as a variable in your class:

    private tree_structure: any = {
        chart: {
            container: "#treant-id",
            levelSeparation: 20,
            siblingSeparation: 15,
            subTeeSeparation: 15,
            rootOrientation: "WEST",

            node: {
                HTMLclass: "treant-class",
                drawLineThrough: true
            },
            connectors: {
                type: "straight",
                style: {
                    "stroke-width": 2,
                    "stroke": "#ccc"
                }
            }
        },

        nodeStructure: {
            text: {
                name: { val: "Djokovic, Novak", href: "http://www.atpworldtour.com/Tennis/Players/Top-Players/Novak-Djokovic.aspx" }
            },
            HTMLclass: "animal",
            image: "/assets/images/flags/can.jpg",
            children: []
        }

(Watch your parentheses here - I've truncated the code above)

I've copied the flags directory with all the images into /assets/images/flags/ and changed the paths in the nodeStructure to reflect that.

I copied all the relevant CSS styles into the component's treant-tree.component.scss file.

If you log out Treant in your constructor, you should see and be able to expand/view the function object just to confirm that the script is loading properly, but this isn't necessary

    `console.log`("Treant",Treant);

Then in ngOnInit, call Treant and pass in the tree-structure variable in an Immediately Invoked Function Expression. The syntax for this in TypeScript is as follows:

ngOnInit() {
    (() => {Treant(this.tree_structure)})();
}

Obviously in order to make actual use of this, you'll want to abstract out the tree-structure data, probably construct it via a service and load it into the component as a parameter or @Input binding, but at least this gets everything working.

Stephen R. Smith
  • 3,310
  • 1
  • 25
  • 41