Search code examples
angulartypescriptmaterializehammer.jsvis.js

Use vis.js with materialize : Uncaught TypeError: Hammer.assign is not a function


I'm trying to run vis.js in an Angular4 project configured with Angular-cli that is already using Materialize-css

When running the angular application I get this error in console :

Uncaught TypeError: Hammer.assign is not a function
    at propagating (vis.js:37731)
    at Object.<anonymous> (vis.js:1915)
    at __webpack_require__ (vis.js:57)
    at Object.<anonymous> (vis.js:34498)
    at __webpack_require__ (vis.js:57)
    at Object.<anonymous> (vis.js:28975)
    at __webpack_require__ (vis.js:57)
    at exports.__esModule (vis.js:100)
    at vis.js:103
    at webpackUniversalModuleDefinition (vis.js:30)

In package.json :

"vis": "4.21.0",
"jquery": "^2.2.4",
"hammerjs": "^2.0.8",
"materialize-css": "^0.100.2",
"angular2-materialize": "^15.1.10",

In angular-cli.json

"styles": [
        "../node_modules/materialize-css/dist/css/materialize.css",
        "../node_modules/vis/dist/vis.min.css",
        "assets/scss/main.scss"
      ],
      "scripts": [
        "../node_modules/jquery/dist/jquery.js",
        "../node_modules/hammerjs/hammer.js",
        "../node_modules/materialize-css/dist/js/materialize.js",
        "../node_modules/vis/dist/vis.min.js"
      ],

I check that hammerjs, jquery, vis and materialize and correctly installed and present in /node_modules directory

hammerjs, jquery and materialize were already installed and working in the project. Which is a simple web site.


Any idea what could lead to this error and how to correct it ?


Solution

  • This is a very difficult question to answer as you don't provide a Minimal, Complete, and Verifiable example.

    It would seem from your question that you are having trouble getting the vis.js library to work in an Angular 4 application. Getting vis.js to work in Angular 4 is quite straightforward. Here are the steps I followed:

    • Create a new project with the cli ng new ng-vis
    • Install the vis library and its typings npm install --save vis @types/vis
    • Add vis styles to the project
      • In the .angular-cli.json file add "../node_modules/vis/dist/vis.css" to the styles array(as you have shown above)
    • Add vis to a view/view-model

      • I updated src/app/app.component.html to <div #vis></div>
      • I then updated src/app/app.component.ts to the following

        import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
        
        import * as vis from 'vis';
        
        @Component({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.css']
        })
        export class AppComponent implements AfterViewInit {
        @ViewChild('vis') element: ElementRef;
        network: vis.Network;
        
        ngAfterViewInit(): void {
          const nodes = new vis.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'}
          ]);
        
          const edges = new vis.DataSet([
            {from: 1, to: 3},
            {from: 1, to: 2},
            {from: 2, to: 4},
            {from: 2, to: 5}
          ]);
        
          const data = {
            nodes: nodes,
            edges: edges
          };
        
          const options = {};
        
          this.network = new vis.Network(this.element.nativeElement, data, options);
         }
        }
        

    You seem to be manually adding your external scripts to the .angular-cli.json file which I would think wouldn't be a best practice. Through utilizing Typescript, you will get the explorability of its type system as well as a few other benefits. The types and certain annotations are what allows Angular to help manage loading of dependencies(possibly the cause of the problem you are describing above) and allows the build system to make smarter decisions when it performs AOT and tree-shaking.

    UPDATE As per Ramesh Rajendran's comment, it is possible that the error is coming from utilizing both materialize-css and vis.js in the same project. From his comment, and the referenced GitHub issue, it would see you should just have to update your .angular-cli.json file to have the following scripts:

      "scripts": [
        "../node_modules/vis/dist/vis.min.js",
        "../node_modules/jquery/dist/jquery.js",
        "../node_modules/hammerjs/hammer.js",
        "../node_modules/materialize-css/dist/js/materialize.js
      ]
    

    Again I would caution you against this approach as it doesn't seem to be in line with best practices. I updated my example to work with both materialize-css and vis.js as follows:

    • Run npm install --save materialize-css @types/materialize-css
    • Update app.component.html

      <div #vis></div>
      
      <ul #collapse class="collapsible" data-collapsible="accordion">
        <li>
          <div class="collapsible-header"><i class="material-icons">filter_drama</i>First</div>
          <div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
        </li>
        <li>
          <div class="collapsible-header"><i class="material-icons">place</i>Second</div>
          <div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
        </li>
        <li>
          <div class="collapsible-header"><i class="material-icons">whatshot</i>Third</div>
          <div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
        </li>
      </ul>
      
    • Update `app.component.ts'

      import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
      
      import * as vis from 'vis';
      import * as $ from 'jquery';
      import 'materialize-css';
      
      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
      })
      export class AppComponent implements AfterViewInit {
        @ViewChild('vis') element: ElementRef;
        @ViewChild('collapse') c_element: ElementRef;
        network: vis.Network;
      
        ngAfterViewInit(): void {
          const nodes = new vis.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'}
          ]);
      
          const edges = new vis.DataSet([
              {from: 1, to: 3},
              {from: 1, to: 2},
              {from: 2, to: 4},
              {from: 2, to: 5}
          ]);
      
          const data = {
              nodes: nodes,
              edges: edges
          };
          const options = {};
      
          this.network = new vis.Network(this.element.nativeElement, data, options);
          $(this.c_element.nativeElement).collapsible();
        }
      }