You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular项目中如何在TypeScript中正确使用Google Chart的JS代码?

Hey there! Let's figure out how to properly work with Google Charts in Angular using TypeScript—your issue with code breaking outside ngOnInit is super common, so let's break this down step by step.

Why does code break outside ngOnInit?

The two main culprits here are:

  1. Angular's lifecycle timing: Code outside ngOnInit runs before the component's DOM is fully rendered. Your chart_div element doesn't exist yet, so trying to access it throws an error.
  2. Google Charts' async loading: The loader.js you added loads the Google Charts library in the background. If your code runs before this library finishes loading, the google global object will be undefined.

ngOnInit is the first Angular lifecycle hook where you can safely interact with the component's DOM and trigger async operations like loading charts—hence why your code works there initially.

Proper TypeScript Implementation

First, we need to tell TypeScript about the global google object (since it's loaded via a script tag, TypeScript doesn't know about it by default). Then we'll structure our code to handle the async chart loading properly.

Step 1: Component Code

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

// Declare the global google object to bypass TypeScript's type checks
declare var google: any;

@Component({
  selector: 'app-google-chart',
  template: '<div id="chart_div" style="width: 100%; height: 400px;"></div>'
})
export class GoogleChartComponent implements OnInit {

  ngOnInit(): void {
    // Load the Google Charts library with the package(s) you need
    google.charts.load('current', { packages: ['corechart'] });
    // Wait for the library to load before drawing the chart
    google.charts.setOnLoadCallback(() => this.drawChart());
  }

  // Extract chart-drawing logic into a reusable private method
  private drawChart(): void {
    // Prepare your chart data
    const chartData = google.visualization.arrayToDataTable([
      ['Task', 'Hours per Day'],
      ['Work',     11],
      ['Eat',      2],
      ['Commute',  2],
      ['Watch TV', 2],
      ['Sleep',    7]
    ]);

    // Configure chart options
    const chartOptions = {
      title: 'My Daily Activities',
      pieHole: 0.4,
      responsive: true
    };

    // Initialize the chart and draw it
    const chart = new google.visualization.PieChart(document.getElementById('chart_div'));
    chart.draw(chartData, chartOptions);
  }
}

Key Notes:

  • declare var google: any;: This tells TypeScript that a global google variable exists, preventing "cannot find name 'google'" errors.
  • google.charts.setOnLoadCallback: Ensures we only draw the chart after the library is fully loaded, avoiding race conditions.

Best Practices for Encapsulation

If you plan to use Google Charts across multiple components, encapsulating the logic into an Angular service is the way to go. This avoids duplicate code and ensures the library is only loaded once.

Step 1: Create a Google Chart Service

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

declare var google: any;

@Injectable({
  providedIn: 'root' // Makes this a singleton service
})
export class GoogleChartService {
  private isLibraryLoaded = false;

  /**
   * Loads the Google Charts library if it hasn't been loaded yet
   * @param packages Array of chart packages to load (default: ['corechart'])
   */
  loadCharts(packages: string[] = ['corechart']): Promise<void> {
    return new Promise((resolve) => {
      if (this.isLibraryLoaded) {
        resolve();
        return;
      }

      google.charts.load('current', { packages });
      google.charts.setOnLoadCallback(() => {
        this.isLibraryLoaded = true;
        resolve();
      });
    });
  }

  /**
   * Draws a pie chart in the specified DOM element
   * @param elementId ID of the container element
   * @param data Chart data in 2D array format
   * @param options Chart configuration options
   */
  drawPieChart(elementId: string, data: any[][], options: any): void {
    const chartData = google.visualization.arrayToDataTable(data);
    const chart = new google.visualization.PieChart(document.getElementById(elementId));
    chart.draw(chartData, options);
  }

  // Add more methods for other chart types (bar, line, etc.) as needed
  drawBarChart(elementId: string, data: any[][], options: any): void {
    const chartData = google.visualization.arrayToDataTable(data);
    const chart = new google.visualization.BarChart(document.getElementById(elementId));
    chart.draw(chartData, options);
  }
}

Step 2: Use the Service in Your Component

import { Component, OnInit } from '@angular/core';
import { GoogleChartService } from './google-chart.service';

@Component({
  selector: 'app-google-chart',
  template: '<div id="chart_div" style="width: 100%; height: 400px;"></div>'
})
export class GoogleChartComponent implements OnInit {

  constructor(private chartService: GoogleChartService) { }

  ngOnInit(): void {
    // Load the library, then draw the chart
    this.chartService.loadCharts().then(() => {
      const activityData = [
        ['Task', 'Hours per Day'],
        ['Work',     11],
        ['Eat',      2],
        ['Commute',  2],
        ['Watch TV', 2],
        ['Sleep',    7]
      ];

      const chartOptions = {
        title: 'My Daily Activities',
        pieHole: 0.4
      };

      this.chartService.drawPieChart('chart_div', activityData, chartOptions);
    });
  }
}

Benefits of This Approach:

  • Single source of truth: The service manages chart loading and drawing logic, so you don't repeat code across components.
  • Avoid duplicate loads: The isLibraryLoaded flag ensures Google Charts is only loaded once, even if multiple components use it.
  • Cleaner components: Components only need to handle data and options, not the low-level chart setup.

Bonus: Responsive Charts

To make your chart resize when the window changes, add a resize listener in your component (don't forget to clean it up to prevent memory leaks):

import { Component, OnInit, OnDestroy } from '@angular/core';
import { GoogleChartService } from './google-chart.service';

@Component({
  selector: 'app-google-chart',
  template: '<div id="chart_div" style="width: 100%; height: 400px;"></div>'
})
export class GoogleChartComponent implements OnInit, OnDestroy {
  private resizeListener: () => void;
  private chartData = [
    ['Task', 'Hours per Day'],
    ['Work',     11],
    ['Eat',      2],
    ['Commute',  2],
    ['Watch TV', 2],
    ['Sleep',    7]
  ];
  private chartOptions = {
    title: 'My Daily Activities',
    pieHole: 0.4
  };

  constructor(private chartService: GoogleChartService) { }

  ngOnInit(): void {
    this.chartService.loadCharts().then(() => {
      this.drawChart();
      // Add resize listener
      this.resizeListener = () => this.drawChart();
      window.addEventListener('resize', this.resizeListener);
    });
  }

  ngOnDestroy(): void {
    // Remove resize listener to prevent memory leaks
    window.removeEventListener('resize', this.resizeListener);
  }

  private drawChart(): void {
    this.chartService.drawPieChart('chart_div', this.chartData, this.chartOptions);
  }
}

内容的提问来源于stack exchange,提问作者user7341673

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:02:25