Using WebComponents with Angular
Angular has good interoperability with WebComponents and, specifically, Custom Elements. There are a few steps that you need to do in order to integrate the GoodData dashboards or insights with the Angular app.
The guide below is based on the Angular template workspace generated using ng new my-app
, but you should be
able to adopt it to existing Angular projects easily.
Load WebComponents library
Add a new <script>
tag to your main HTML file (src/index.html
).
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>NgApp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
+ <script type="module" async src="{your-gd-server-url}/components/{workspace-id}.js?auth=sso"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
See WebComponents introduction page. Make sure to go through the Prerequisites and limitations section.
Add custom elements schema
Add CUSTOM_ELEMENTS_SCHEMA
to your main module (src/app/app.module.ts
). Otherwise, Angular will warn you about
unknown components.
- import { NgModule } from '@angular/core';
+ import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent],
+ schemas: [
+ CUSTOM_ELEMENTS_SCHEMA,
+ ]
})
export class AppModule { }
Embed visualizations
You can now use gd-insight
and gd-dashboard
elements anywhere in your src/app/app.component.html
template.
<gd-insight insight="my-insight-id" style="height:500px"></gd-insight>
<gd-dashboard dashboard="my-dashboard-id"></gd-dashboard>
You can copy the insight id and dashboard id from the URL bar of your web browser, from the Analyze and Dashboards pages respectively. At this point you should see an insight and a dashboard rendering on the screen.
We set the height of the gd-insight
to a static value as it’s expecting a flex layout and would collapse to a 0
height
otherwise.
Define dashboardId and insightId dynamically
You can use attribute binding to define the IDs dynamically from the Angular component code.
Define component variables in src/app/app.component.ts
:
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ng-app';
+ dashboardId = 'my-dashboard-id';
+ insightId = 'my-insight-id';
}
Update the src/app/app.component.html
template:
<gd-insight [attr.insight]="insightId" style="height:500px"></gd-insight>
<gd-dashboard [attr.dashboard]="dashboardId"></gd-dashboard>
Add event listeners
Both gd-insight
and gd-dashboard
are dispatching custom events.
Insight event listener
In case of gd-insight
you can use the Angular event binding syntax. Define an event listener function in
your component code (src/app/app.component.ts
):
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ng-app';
dashboardId = 'my-dashboard-id';
insightId = 'my-insight-id';
+
+ onInsightLoaded(e: Event) {
+ console.log((e as CustomEvent).detail);
+ }
}
Attach the event listener to the insight at src/app/app.component.html
:
<gd-insight [attr.insight]="insightId" style="height:500px" (insightLoaded)="onInsightLoaded($event)"></gd-insight>
Read more about Insight events.
Dashboard event listener
The setup for gd-dashboard
is more complicated, as event names do not follow Angular naming convention. You would
need to obtain a reference to the DOM object and add event listeners directly.
First, use the template reference variable to mark the dashboard element in src/app/app.component.html
:
<gd-dashboard [attr.dashboard]="dashboardId" #dashboard></gd-dashboard>
Now you can obtain the element and attach event listeners in src/app/app.component.ts
. Keep in mind that you
also need to remove the listeners on the component unmount.
- import { Component } from "@angular/core";
+ import { Component, ViewChild } from "@angular/core";
+
+ const EVENT_NAME = 'GDC.DASH/EVT.INITIALIZED';
+
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ng-app';
dashboardId = 'my-dashboard-id';
insightId = 'my-insight-id';
+ private myDashboardElement?: HTMLElement;
onInsightLoaded(e: Event) {
console.log((e as CustomEvent).detail);
}
+
+ onDashboardLoaded(e: Event) {
+ console.log((e as CustomEvent).detail);
+ }
+
+ @ViewChild("dashboard")
+ set dashboard(d: any) {
+ this.myDashboardElement = d.nativeElement;
+ this.myDashboardElement?.addEventListener(EVENT_NAME, this.onDashboardLoaded);
+ }
+
+ ngOnDestroy() {
+ this.myDashboardElement?.removeEventListener(EVENT_NAME, this.onDashboardLoaded);
+ }
}