11

I'm trying to use a visjs lib but can't make their getting started example working it goes like this:

<script type="text/javascript">
    // DOM element where the Timeline will be attached
    var container = document.getElementById('visualization');

    // Create a DataSet (allows two way data-binding)
    var items = new vis.DataSet([
        {id: 1, content: 'item 1', start: '2013-04-20'},
        {id: 2, content: 'item 2', start: '2013-04-14'},
        {id: 3, content: 'item 3', start: '2013-04-18'},
        {id: 4, content: 'item 4', start: '2013-04-16', end: '2013-04-19'},
        {id: 5, content: 'item 5', start: '2013-04-25'},
        {id: 6, content: 'item 6', start: '2013-04-27'}
    ]);

    // Configuration for the Timeline
    var options = {};

    // Create a Timeline
    var timeline = new vis.Timeline(container, items, options);
</script>
YakovL
  • 7,557
  • 12
  • 62
  • 102
CommonSenseCode
  • 23,522
  • 33
  • 131
  • 186

4 Answers4

21

Please find below code that using angular2 with vis and you just need to install vis and import it. In this example i have created a angular2 component for vis library.

import { Component , OnInit, OnDestroy } from '@angular/core';
import { Network, DataSet, Node, Edge, IdType } from 'vis';
@Component({
  selector: 'network-graph',
  templateUrl: './network-graph.component.html'
})
export class NetworkGraphComponent implements OnInit{
    public nodes: Node;
    public edges: Edge;
    public network : Network;

    public ngOnInit(): void {
          var nodes = new DataSet([
              {id: 1, label: 'Node 1'},
              {id: 2, label: 'Node 2'},
              {id: 3, label: 'Node 3'},
              {id: 4, label: 'Node 4'},
              {id: 5, label: 'Node 5'}
          ]);
            // create an array with edges
            var edges = new DataSet([
              {from: 1, to: 3},
              {from: 1, to: 2},
              {from: 2, to: 4},
              {from: 2, to: 5},
              {from: 3, to: 3}
            ]);
           // create a network
          var container = document.getElementById('mynetwork');
          var data = {
            nodes: nodes,
            edges: edges
          };
          var options = {};
          var network = new Network(container, data, options);
    }
}
meenu1meen
  • 210
  • 2
  • 7
  • 1
    Whilst this code snippet is welcome, and may provide some help, it would be [greatly improved if it included an explanation](//meta.stackexchange.com/q/114762) of *how* it addresses the question. Without that, your answer has much less educational value - remember that you are answering the question for readers in the future, not just the person asking now! Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Apr 26 '17 at 07:44
  • This answer is perfectly OK for someone with a background in Angular 2. – Soumya Kanti Aug 11 '17 at 10:26
  • 1
    I would love to know how you import vis, and whether you use closure to compile the project or not.... – magor Aug 28 '17 at 13:06
  • No it is simple angular cli application and i npm install vis and simply include it in my component. I did not import vis in module file. – meenu1meen Sep 27 '17 at 07:51
12

Here is a simple plunker integrating the code you posted with Angular 2 https://plnkr.co/edit/TbPTfXFk4RSAuPn4BBxP?p=preview

In this example the integration is in OnInit

ngOnInit() {
    var container = document.getElementById('visualization');

    // Create a DataSet (allows two way data-binding)
    var items = new vis.DataSet([
        {id: 1, content: 'item 1', start: '2013-04-20'},
        {id: 2, content: 'item 2', start: '2013-04-14'},
        {id: 3, content: 'item 3', start: '2013-04-18'},
        {id: 4, content: 'item 4', start: '2013-04-16', end: '2013-04-19'},
        {id: 5, content: 'item 5', start: '2013-04-25'},
        {id: 6, content: 'item 6', start: '2013-04-27'}
    ]);

    // Configuration for the Timeline
    var options = {};

    // Create a Timeline
    var timeline = new vis.Timeline(container, items, options);
  }
TGH
  • 38,769
  • 12
  • 102
  • 135
11

Using angular directives would be a clean approach to solve this problem. Let's start with installing vis.js

npm install vis

Component that displays the vis chart should have a container element for the chart., let's say

graph-visualization.component.html

<div [appGraphVis]="graphData" class="graph-container"></div>

graph-visualization.component.css

.graph-container {
    height: 25em;
    widows: 100%;
}

graph-visualization.component.ts

import { Component, OnInit } from '@angular/core';
import { DataSet } from 'vis';

@Component({
  selector: 'app-graph-visualization',
  templateUrl: './graph-visualization.component.html',
  styleUrls: ['./graph-visualization.component.css']
})
export class GraphVisualizationComponent {
  graphData = {};

  constructor() { }

  ngAfterContentInit(){
    // create an array with nodes
    var nodes = new DataSet([
      {id: 1, label: 'Node 1'},
      {id: 2, label: 'Node 2'},
      {id: 3, label: 'Node 3'},
      {id: 4, label: 'Node 4'},
      {id: 5, label: 'Node 5'}
    ]);

    // create an array with edges
    var edges = new DataSet([
      {from: 1, to: 3},
      {from: 1, to: 2},
      {from: 2, to: 4},
      {from: 2, to: 5}
    ]);

    // provide the data in the vis format
    this.graphData["nodes"] = nodes;
    this.graphData["edges"] = edges;
  }

}

Notice few things:

  • this component only computes the data that need to be visualized and it doesn't do anything, like manupulating the DOM or use vis.js directly. Since vis.js is a DOM manulation, We could have a directive that handles it
  • Used ngAfterContentInit rather than ngOnInit. This will delay the graph generation part and allow other DOM related tasks to complete

graphvis.directive.ts

import { Directive, TemplateRef, ViewContainerRef, Input, Renderer2, ElementRef } from '@angular/core';
import { Network } from 'vis';

@Directive({
  selector: '[appGraphVis]'
})
export class GraphVisDirective {
  network;

  constructor(private el: ElementRef) {}

  @Input() set appGraphVis(graphData){
    console.log('graph data ', graphData);
    var options = {};

    if(!this.network){
      this.network = new Network(this.el.nativeElement, graphData, options);
    }

  }

}

For simplicity, I have kept the options inside directive. In real world, options will be passed as another input from high level component.

Additional notes, we could add typescript's types for vis to help during development and debugging. It's available here:

yarn add @types/vis -D

If you are looking for a ready to use solution, check out this library - angular-vis. At the time of writing this, it doesn't support all features of vis.js

Sairam Krish
  • 10,158
  • 3
  • 55
  • 67
1

Well, some modifications needed for the code proposed above which took me a while to by-pass ... so I share these :

1) you need to access the container by @ViewChild('netWords') netContainer: ElementRef; and #netWords in the html part.

2) you need to access fully the container element using the nativeElement property, so this would be this.network = new Vis.Network(this.netContainer.nativeElement, data, options);

It should work with these modifications.

Marc
  • 11
  • 2