在Angular 8应用程序中使用外部JavaScript库

时间:2019-09-30 11:03:16

标签: javascript angular typescript

我是Angular的新手,我想开发一个漏斗图。我喜欢funnel-graph-js库。我尝试了很多,但没有成功。

这是我的funnel-graph-directive.ts

import { Directive, ElementRef } from '@angular/core';

// import * as graph from '../../../assets/js/funnel-graph.js';
import * as graph from 'funnel-graph-js/dist/js/funnel-graph.js';
var graph = new FunnelGraph({
  container: '.funnel',
  gradientDirection: 'horizontal',
  data: {
    labels: ['Impressions', 'Add To Cart', 'Buy'],
    subLabels: ['Direct', 'Social Media', 'Ads'],
    colors: [
      ['#FFB178', '#FF78B1', '#FF3C8E'],
      ['#A0BBFF', '#EC77FF'],
      ['#A0F9FF', '#7795FF']
    ],
    values: [
      [3500, 2500, 6500],
      [3300, 1400, 1000],
      [600, 200, 130]
    ]
  },
  displayPercent: true,
  direction: 'horizontal'
});

graph.draw();
@Directive({
  selector: '[appFunnelGraph]'
})
export class FunnelGraphDirective {
  style: any;
  constructor(el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';
  }
}

我已在我的angular.json

中添加了这些行
"styles": [
  "src/styles.scss",
  "./node_modules/funnel-graph-js/dist/css/main.css",
  "./node_modules/funnel-graph-js/dist/css/theme.css"
],
"scripts": [
  "./node_modules/funnel-graph-js/dist/js/funnel-graph.js"
]

这是我遇到的错误 enter image description here

2 个答案:

答案 0 :(得分:2)

只要您在html中链接了javascript文件,它就可以正常工作。

编辑:

包含附加的javascript文件的一种更好的方法是将其放入 angular.json 文件的“脚本”部分。您也可以添加

declare const FunnelGraph: any

以便编译没有错误。取自an answer to a stackoverflow questionthis guide。记住也要在该json中包含css文件!

编辑结束

您会收到此错误,因为代码试图使用名为“ funnel”的类查找HTML元素,但找不到它。由于这是一条指令,因此如果将其更概括一点会更好。

首先,应该将图形生成代码移到构造函数中,因为这就是指令逻辑所在的位置。为了更好地概括该指令,最好是给该元素一个唯一的ID,然后相应地更改代码。这就是我的方法:

HTML:

<div id="funnel-graph-1" appFunnelGraph></div>

JS:

import { Directive, ElementRef } from '@angular/core';

// It should be fine to just import this in the html with a script tag
// import * as graph from 'funnel-graph-js/dist/js/funnel-graph.js';

@Directive({
  selector: '[appFunnelGraph]'
})
export class FunnelGraphDirective {
  style: any;
  constructor(el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';

    var graph = new FunnelGraph({
      // Generalize the container selector with the element id
      container: '#' + el.nativeElement.id,
      gradientDirection: 'horizontal',
      data: {
        labels: ['Impressions', 'Add To Cart', 'Buy'],
        subLabels: ['Direct', 'Social Media', 'Ads'],
        colors: [
          ['#FFB178', '#FF78B1', '#FF3C8E'],
          ['#A0BBFF', '#EC77FF'],
          ['#A0F9FF', '#7795FF']
        ],
        values: [
          [3500, 2500, 6500],
          [3300, 1400, 1000],
          [600, 200, 130]
        ]
      },
      displayPercent: true,
      direction: 'horizontal'
    });

    graph.draw();
  }
}

答案 1 :(得分:1)

最后我创建了service而不是使用directive方法。

  • 首先,我在中生成了一个名为dynamic-script-loader-service的服务 我的dashboard模块。
  

dynamic-service-loader.service.service.ts

import { Injectable } from '@angular/core';

interface Scripts {
  name: string;
  src: string;
}

export const ScriptStore: Scripts[] = [
  { name: 'chartjs', src: 'https://unpkg.com/funnel-graph-js@1.3.9/dist/js/funnel-graph.min.js' },
];

declare var document: any;

@Injectable()
export class DynamicScriptLoaderServiceService {

  private scripts: any = {};

  constructor() {
    ScriptStore.forEach((script: any) => {
      this.scripts[script.name] = {
        loaded: false,
        src: script.src
      };
    });
  }

  load(...scripts: string[]) {
    const promises: any[] = [];
    scripts.forEach((script) => promises.push(this.loadScript(script)));
    return Promise.all(promises);
  }

  loadScript(name: string) {
    return new Promise((resolve, reject) => {
      if (!this.scripts[name].loaded) {
        //load script
        let script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.scripts[name].src;
        if (script.readyState) {  //IE
          script.onreadystatechange = () => {
            if (script.readyState === 'loaded' || script.readyState === 'complete') {
              script.onreadystatechange = null;
              this.scripts[name].loaded = true;
              resolve({ script: name, loaded: true, status: 'Loaded' });
            }
          };
        } else {  //Others
          script.onload = () => {
            this.scripts[name].loaded = true;
            resolve({ script: name, loaded: true, status: 'Loaded' });
          };
        }
        script.onerror = (error: any) => resolve({ script: name, loaded: false, status: 'Loaded' });
        document.getElementsByTagName('head')[0].appendChild(script);
      } else {
        resolve({ script: name, loaded: true, status: 'Already Loaded' });
      }
    });
  }

}
  

dashboard.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { DynamicScriptLoaderServiceService } from '../dynamic-script-loader-service.service';
import * as FunnelGraph from 'funnel-graph-js';

function dashboardFunnel() {
  const graph = new FunnelGraph({
    container: '.funnel',
    // gradientDirection: 'horizontal',
    data: {
      labels: ['Label 7', 'Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5', 'Label 6'],
      colors: ['#00A8FF', '#00A8FF', '#00A8FF', '#00A8FF', '#00A8FF', '#00A8FF', '#00A8FF'],
      // color: '#00A8FF',
      values: [12000, 11000, 10000, 9000, 8000, 7000, 6000]
    },
    displayPercent: true,
    direction: 'horizontal',
  });

  graph.draw();
}

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class DashboardComponent implements OnInit {

  constructor(
    private dynamicScriptLoader: DynamicScriptLoaderServiceService
  ) {}


  ngOnInit() {
    this.loadScripts();
    dashboardFunnel();
  }

  private loadScripts() {
    // You can load multiple scripts by just providing the key as argument into load method of the service
    this.dynamicScriptLoader.load('chartjs', 'random-num').then(data => {
      // Script Loaded Successfully
    }).catch(error => console.log(error));
  }

}
  

在我的providers中添加了dashboard.module.ts

providers: [DynamicScriptLoaderServiceService],
  

在我的css中添加了angular.json

"styles": [
              "src/styles.scss",
              "./node_modules/funnel-graph-js/dist/css/main.css",
              "./node_modules/funnel-graph-js/dist/css/theme.css"
            ],

div中为funnel添加了类dashboard.component.html

<div class="funnel"></div>