【问题标题】:Google charts (jsapi) into angular2 component谷歌图表(jsapi)到angular2组件
【发布时间】:2016-02-21 04:56:52
【问题描述】:

我正在努力创建一个可以调用 google chart api 并显示 google-chart (https://developers.google.com/chart/interactive/docs/quick_start) 的 angular2 组件。这通常会导致无法解释的错误,或者只是浏览器永远加载。

编辑:下面添加了完整更新的测试文件

另请参阅 plnkr here

更具体地说,这些是我用来确定问题开始点的测试文件:

index.html

<html>
<head>
<title>Angular 2 QuickStart</title>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.46/angular2.dev.js">    </script>

<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>


<script>
  System.config({
    transpiler: 'typescript',
    typescriptOptions: { emitDecoratorMetadata: true }
  });
  System.import('./app.ts');
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>

然后,app.ts

import {bootstrap, Component} from 'angular2/angular2';


@Component({
selector: 'my-app',
template:`
<h1>Demo component my-app</h1>
<div id="cc" (click)="test($event)">Click me</div>
`
})
class AppComponent {

constructor() {
console.log("Constructor was called");
}

test(event) {
console.log("Event :",event);
console.log("Test :", google);
console.log("Document object by id",document.getElementById("cc"));

// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {

  console.log("Callback is entered ");

  // Create the data table.
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'Topping');
  data.addColumn('number', 'Slices');
  data.addRows([
    ['Mushrooms', 3],
    ['Onions', 1],
    ['Olives', 1],
    ['Zucchini', 1],
    ['Pepperoni', 2]
  ]);

  // Set chart options
  var options = {'title':'How Much Pizza I Ate Last Night',
                 'width':400,
                 'height':300};

  // Instantiate and draw our chart, passing in some options.
  var chart = new   google.visualization.PieChart(document.getElementById('cc'));
  chart.draw(data, options);
}



  console.log("Google object : ", google);
  console.log("Now, loading visualization api");
  // Load the Visualization API and the piechart package.
  google.load('visualization', '1.0', {'packages':['corechart']});
  console.log("Now, setting callback");
  // Set a callback to run when the Google Visualization API is loaded.
  google.setOnLoadCallback(drawChart);
  console.log("Callback was set");
  }

}



bootstrap(AppComponent);

这是控制台显示的内容,当我单击时:

Constructor was called
app.ts:18 Event : MouseEvent {isTrusted: true}
app.ts:19 Test : Object {loader: Object}
app.ts:20 Document object by id <div id=​"cc">​Click me​</div>​
app.ts:53 Google object :  Object {loader: Object}
app.ts:54 Now, loading visualization api
app.ts:57 Now, setting callback
app.ts:60 Callback was set

显然,回调从来没有进入?!

谁能帮我解决这个问题?非常感谢!

【问题讨论】:

  • 您应该在index.html 中为jsapi 脚本添加一个脚本标签,然后它将在您的组件中的全局范围内,因此您不需要要求或导入它。
  • @rob 感谢您抽出宝贵时间回答!我意识到我的问题不够具体,并对其进行了编辑。我真正想做的是确保在开始移植当前使用 angular1 的现有应用程序之前,我可以获得一个简单的图形,例如来自 google-visualisation 的快速启动图形示例以在 angular2 组件中运行,其中所有我的图表和数据结构基于 google-visualization ...
  • PrimeNG 的图表组件可以提供帮助。 primefaces.org/primeng/#/piechart

标签: javascript typescript google-visualization angular


【解决方案1】:

最后,通过使用图表组件调用图表指令来解决它。该指令的设置器触发绘图。不再需要直接捕获/管理绘图事件。

  1. 从顶部 index.html 文件加载 google 脚本

    <script type="text/javascript" src="https://www.google.com/jsapi">
    </script>
    <script type="text/javascript">        
      google.load('visualization', '1.0', {
        'packages': ['corechart']
      });
    </script>
    
  2. 创建一个“图表”指令来绘制谷歌图表(chart.directive.ts)

    /**
    *      This directive will draw a chart from the array of records provided
    *
    *           Note : the relevant jsapi scripts should be already available
    *                  globally in the window.google object (see index.html)
    **/
    
    import {Directive, ElementRef, Input} from "angular2/core";
    import {CORE_DIRECTIVES } from "angular2/common";
    
    @Directive({
      selector: "chart",
    })
    export class ChartDirective {
    
      el: HTMLElement; 
      w: any;  // To store the window, without generating errors in typescript on window.google
      private _content: any[] = [];         
    
      // Setter for content will trigger drawing (or refreshing)
      @Input()
      set content(c: any[]) {
        console.log("Setting content ...");
        this._content = c;
        this.draw();
      }
    
      get content() { return this._content; }
    
    
    
      // Constructor inject a ref to the element
      constructor(elementRef: ElementRef) {
      console.log("Constructing chart directive");
      this.w = window;
      this.el = elementRef.nativeElement; // You cannot use elementRef directly !
      // console.log("Native HTML :", this.el);
      if (!this.w.google) { console.error("Hey ! It seems the needed google script was not loaded ?"); };
      }
    
    // Do the actual drawing
    draw() {
      // Create the data table.
      let data = new this.w.google.visualization.DataTable();
      data.addColumn("date", "Quand");
      data.addColumn("number", "KG");
      let rows = [];
      for (let c in this._content) {
        let d: Date = new Date(this._content[c].quand);
        let k: number = +(this._content[c].kg); // Plus sign to force conversion sting -> number
        // Only take into account records after the 'notBefore date'
        if (d >= this._nbd) rows.push([d, k]);
      }
      data.addRows(rows);
      // Create options
      let options: any = {
        // "width": 600,
        "height": 300,
        "curveType": "function"
      };
    
    
      // Instantiate and draw our chart, passing in some options.
      (new this.w.google.visualization.LineChart(this.el))
        .draw(data, options);
    }
    

    }

  3. 在图表组件(chart.component)中使用该指令...

    import {Component } from "angular2/core";
    import {CORE_DIRECTIVES } from "angular2/common";
    
    import {MyModel} from "./mymodel.service.ts";
    import {ChartDirective} from "./chart.directive.ts";
    
    
    @Component({
    selector: "chartPage",
    templateUrl: "/components/chart.template.html",
    directives: [CORE_DIRECTIVES, ChartDirective]        
    })
    export class ChartComponent {     
    
    }
    
    // Injecting my data model into chart component ...
    constructor(private model: MyModel) {
      console.log("Constructing chart component");
    };
    

    }

  4. ...使用以下图表模板

    <chart [content]="model.content" ></chart>
    

【讨论】:

  • 文件chart.directive.ts中的this._nbd是什么?
  • 感谢您的详细回答,但我仍然无法理解这一点。有人可以分享有效的 GoogleCharts+Angular2 项目目录吗?在此先感谢:)
【解决方案2】:

我在尝试将谷歌图表实现到 ionic2 时遇到了同样的问题。我不确定到底是什么问题,但似乎

  google.load('visualization', '1.0', {'packages':['corechart']});

加载时间过长

  google.setOnLoadCallback(drawChart);

永远不会被执行。您可以通过将回调直接添加到 google.load() 来绕过它,如下所示:

    google.load('visualization', '1.0', {'packages':['corechart'], callback: drawChart});

为我工作!并且图表正在根据需要加载。此解决方案的所有功劳归于@davidkonrad:

https://stackoverflow.com/a/31040694

希望它有效!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多