This solution is suited if you are using routing. You can create a Resolver
that will initialize and resolve the google
object, which you can inject into your component.
First you need to add the below line to the end of index.html
// index.html
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
Then you need to create a Resolver
say, named GoogleChartResolver
.
// shared/google-chart.resolver.ts
declare const google: any;
@Injectable()
export class GoogleChartResolver implements Resolve<any>{
private static googleChartLoaded: boolean = false;
constructor() {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if(GoogleChartResolver.googleChartLoaded){
return Observable.of(google);
} else {
return Observable.create(function (observer: Observer<any>) {
google.charts.load('current', {packages: ['corechart', 'bar']});
google.charts.setOnLoadCallback(() => {
observer.next(google);
observer.complete();
GoogleChartResolver.googleChartLoaded = true;
});
});
}
}
}
For every route and component you need an instance of google
, you can add the below lines. You need to add the GoogleChartResolver
to the list of Observables to be resolved for the route,
// app-routing.module.ts
{path: 'my-path', component: MyComponent, resolve: {google: GoogleChartResolver}}
In the MyComponent
you can inejct ActivatedRoute
and get the instance of google
from the snapshot
// my.component.ts
private google: any;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.google = this.route.snapshot.data.google;
drawChart(this.google)
}
All the dependent resources for the Google charts will be loaded during the first time you try to resolve the Resolver (here, the first time you visit /my-path
). On subsequent resolutions, already resolved object is returned (no resource fetch required). Also this approach loads all Chart packages at once.
If you need to optimize further, you can load different chart packages using different resolvers, but that may be an overkill, a solution for this will be, instead of creating Resolver
classes, you can achieve route resolve
functionality using method reference (say create a static method in a service which does the same thing).