How to make vis.js lib to work with Angular2?
Asked Answered
F

4

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>
Foible answered 28/10, 2016 at 1:55 Comment(0)
R
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);
  }
Rohn answered 28/10, 2016 at 2:6 Comment(5)
how to do you get a reference to vis?Foible
Thanks for making it work, but I get error: app.module.ts:40:24 Cannot find name 'vis'.Foible
ok finally made it work many thanks! is there any way to put this inside an angular 2 component?Foible
I updated the component to also be the target element of the vis libraryRohn
Also added declare var vis: any; which declares the vis variable. You can maybe install typings for this library if it exists, but declaring it as an any is probably ok unless you need to call multiple methods on itRohn
K
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);
    }
}
Kerouac answered 26/4, 2017 at 6:43 Comment(4)
Whilst this code snippet is welcome, and may provide some help, it would be greatly improved if it included an explanation 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.Daggett
This answer is perfectly OK for someone with a background in Angular 2.Hesper
I would love to know how you import vis, and whether you use closure to compile the project or not....Arbuckle
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.Kerouac
R
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);
  }
Rohn answered 28/10, 2016 at 2:6 Comment(5)
how to do you get a reference to vis?Foible
Thanks for making it work, but I get error: app.module.ts:40:24 Cannot find name 'vis'.Foible
ok finally made it work many thanks! is there any way to put this inside an angular 2 component?Foible
I updated the component to also be the target element of the vis libraryRohn
Also added declare var vis: any; which declares the vis variable. You can maybe install typings for this library if it exists, but declaring it as an any is probably ok unless you need to call multiple methods on itRohn
T
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

Totter answered 12/4, 2018 at 12:35 Comment(0)
C
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.

Comeau answered 7/4, 2018 at 7:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.