What is the process for embedding a Google Chart within an Angular 4 application?

What is the process of integrating a Google chart in an Angular 4 application?

After reading the answer to a question on Stack Overflow here, I realized that there were some missing details. Following a similar approach as mentioned in the previous answer, I encountered two errors. The first error was the absence of a call to super() for the child component and the second error occurred due to the use of "new" in this code snippet:

createBarChart(element: any): any {
    return new google.visualization.BarChart(element);
}

The error message displayed was "google.visualization.BarChart is not a constructor".

I also noticed a comment suggesting the use of <ng-content> for data projection but it wasn't clearly explained.

In an effort to formulate a detailed question, here is my GoogleChartComponent:

export class GoogleChartComponent implements OnInit {
    private static googleLoaded: any;
    constructor() {
        console.log('Here is GoogleChartComponent');
    }

    getGoogle() {
        return google;
    }

    ngOnInit() {
        console.log('ngOnInit');
        if (!GoogleChartComponent.googleLoaded) {
            GoogleChartComponent.googleLoaded = true;
            google.charts.load('current', {
                'packages': ['bar']
            });
            google.charts.setOnLoadCallback(() => this.drawGraph());
        }
    }

    drawGraph() {
        console.log('DrawGraph base class!!!! ');
    }

    createBarChart(element: any): any {
        return new google.visualization.BarChart(element);
    }

    createDataTable(array: any[]): any {
        return google.visualization.arrayToDataTable(array);
    }
}

And here is the child component that extends it:

@Component({
    selector: 'app-bitcoin-chart',
    template: `
       <div id="barchart_material" style="width: 700px; height: 500px;"></div>
    `,
    styles: []
})
export class BitcoinChartComponent extends GoogleChartComponent  {
    private options;
    private data;
    private chart;

    drawGraph() {
        console.log('Drawing Bitcoin Graph');
        this.data = this.createDataTable([
            ['Price', 'Coinbase', 'Bitfinex', 'Poloniex', 'Kraken'],
            ['*', 1000, 400, 200, 500]
        ]);

        this.options = {
            chart: {
                title: 'Bitcoin Price',
                subtitle: 'Real time price data across exchanges',
            },
            bars: 'vertical' // Required for Material Bar Charts.
        };

        this.chart = this.createBarChart(document.getElementById('barchart_material'));
        this.chart.draw(this.data, this.options);
    }
}

Answer №1

In my opinion, there is a more effective approach to incorporating Google Chart in Angular 4 using the ng2-google-charts library. This library already provides the GoogleChartComponent which can be easily implemented by following the instructions on its npm page. Below is an example of how the component can be used:

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

import {GoogleChartComponent} from 'ng2-google-charts';

// Additional imports for advanced usage
import {HostListener} from '@angular/core';

@Component({
  selector: '[your-widget]',
  templateUrl: './your-widget.html',
  encapsulation: ViewEncapsulation.None
})
export class YourWidget implements OnInit {

  @ViewChild('your_chart') chart: GoogleChartComponent;

  showSpinner: boolean;

  public chartData = {
    chartType: 'AnyChartType', // specify your chart type
    dataTable: [
      ['Col1', 'Col2']
    ],
    options: {}
  };

  constructor() {
  }

  ngOnInit(): void {

    this.showSpinner = true;
    this.yourService.getData()
          .subscribe((data) => {
            this.processYourData();
            this.showSpinner = false;
        });
      }

  private processYourData() {
  }

  @HostListener('window:resize', ['$event'])
  onWindowResize(event: any) {
    this.chart.redraw(); 
  }
}

Your HTML markup could look like this:

<header class="widget-handle">
  <h5>Widget Title</h5>
  <div class="widget-controls">
    <a title="Refresh">
      <i *ngIf="showSpinner" class="fa fa-refresh fa-spin"></i>
    </a>
  </div>
</header>

<div class="widget-body">
  <google-chart #your_chart [data]="chartData" *ngIf="!showSpinner">
  </google-chart>
</div>

Answer №2

google.visualization.BarChart is a component of the 'corechart' package

We need to update the loading statement...

  google.charts.load('current', {
    'packages': ['corechart']
  });

The 'bar' package is specifically designed for the Material chart version
and should be -> google.charts.Bar

However, there are certain configuration options that are not compatible with Material charts...

For a comprehensive list of unsupported features --> Tracking Issue for Material Chart Feature Parity

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to reach the margin-left properties of the elements

I am facing an issue in accessing the current margin-left CSS property of the class .circle in the code snippet below. A demonstration of this problem can be found on a website called PLUNKr. The reason I need to access this property is because I have to ...

Issues with Vite's global import feature not functioning properly in a production build

My current setup involves loading all markdown files within a directory using a glob import. The code snippet below depicts this functionality: const useGetChangelogs = () => { const [changelogs, setChangelogs] = useState<string[]>([]); useEf ...

Leveraging Angular to utilize services within objects, or alternatively constructing objects by incorporating services within their

I am currently working with a form setting that looks like this: export const fields = [ { key: 'key', options: myService.get() // how can I call service method here? } ] Recently, I had the thought of structuring it differently b ...

What is the correct way to effectively integrate react-hook-form with redux and typescript?

After tirelessly searching for a comprehensive guide that could demonstrate all these requirements in one example, I eventually resorted to brute force to make something functional. However, I am well aware that this approach is not the correct way to achi ...

Error message "Property 'name' does not exist on type '{}'" is encountered when using Ionic/Angular HttpClient and no data type is specified

While working on my Ionic project, I encountered an error in Angular when trying to fetch data from an API using HttpClient. The error message that popped up was 'Property 'name' does not exist on type '{}'.'. Below is the cod ...

Utilize the import feature to bring in a paragraph from a separate file within your

Hey there! I've encountered a little issue. I'm trying to access an object from another component in the ability.component.html file but for some reason, the last paragraph (h1) is not functioning properly. Any idea why? app.component.ts @Compo ...

Transfer a file to Laravel using $request->input()

Is there a way to upload my file to FTP when I'm sending the data from Angular using JSON format instead of using $request->file("Fichier1") in Laravel? Here is an example of how the data is sent from Angular to Laravel: https://i.stack. ...

Discovering a solution to extract a value from an Array of objects without explicitly referencing the key has proven to be quite challenging, as my extensive online research has failed to yield any similar or closely related problems

So I had this specific constant value const uniqueObjArr = [ { asdfgfjhjkl:"example 123" }, { qwertyuiop:"example 456" }, { zxcvbnmqwerty:"example 678" }, ] I aim to retrieve the ...

Using child routes in eager loaded components can be achieved without making any changes to

In many tutorials, I have noticed that RouterModule.forChild(..) is commonly used for lazy loading. However, I am of the opinion that this forChild method can also be utilized for eager loading. Its advantage lies in the fact that routes can be configured ...

Tips for designing a search bar using Angular

search : ____________ I am interested in designing a search bar functionality that automatically triggers when the user inputs 8 or more characters. The input text will be stored in a variable, the search bar will be reset, and the backend API will be che ...

The Vercel/NextJS deployment does not delay the completion of the serverless function until the email is sent via Azure

Upon a user's registration, I am attempting to send a registration/account activation email. While the email sends successfully via Azure's email services when running on localhost, deployments on Vercel do not trigger the email (although the use ...

Tips for adjusting the dimensions of a child element to match its parent in Angular 12 with Typescript

I have included the child component in the parent component and I am displaying that child component within a col-md-8. What I want to achieve is to highlight a specific div in the child component with additional text, making it equal in size to the parent ...

The AngularJS DirectiveLinkFn interface is a powerful tool for creating dynamic

Guidelines for implementing the directive's link method in TypeScript involve using the fourth parameter as an instance of ng.INgModelController public link($scope: ng.IScope, el: JQuery, attrs: ng.IAttributes, ngModel: ng.INgModelController) Howeve ...

Experiencing a 404 ERROR while attempting to submit an API POST request for a Hubspot form within a Next.js application

Currently, I am in the process of developing a Hubspot email submission form using nextjs and typescript. However, I am encountering a couple of errors that I need help with. The first error pertains to my 'response' constant, which is declared b ...

Saved values fail to load in Angular mat-checkboxes

My checkbox implementation is a bit unique from the norm. Within my form group, I have a single form control that, when saved, contains an array of checked values. However, upon saving and reloading the data, the checkboxes do not retain their checked stat ...

Create a one-of-a-kind Angular 6 material table component featuring unique custom columns

My goal is to streamline the process of creating custom material tables by using a specialized table component that allows me to quickly generate unique tables for different data sources with built-in pagination and sorting. All I need to provide are the d ...

Guide to integrating a fruit product checklist within a React application

Seeking assistance in incorporating a checklist into my react application, to only be visible after a specific button is clicked. Upon reviewing productFruit's documentation, it appears that I need to utilize the following code snippet: useEffect(() ...

When communicating with the Rails 5 API, ensure that the post request in Angular 4/Ionic 2 includes the necessary `registration` field

Within my Ionic2/Angular4 application, I have implemented the following method: const body = JSON.stringify(values); let headers = new Headers(); headers.append('Content-Type', 'application/json'); console.log(body) return this.http. ...

Using Angular, we can make an HTTP call and map the response to an

I have a function that fetches information from a REST API in this format: getProducts(category: string): Observable<IProduct[]> { let url = `/rest/getproducts?category=${category}`; return this._http.get<IProduct[]>(url); } The dat ...

Using createStyles in TypeScript to align content with justifyContent

Within my toolbar, I have two icons positioned on the left end. At the moment, I am applying this specific styling approach: const useStyles = makeStyles((theme: Theme) => createStyles({ root: { display: 'flex', }, appBar: ...