Dashboards and Dashboard Widgets - Part 1
In a previous post, I wrote about Angular Material's toolbar and sidenav components.
In this post, I'll walk you through the steps I followed in order to add Dashboard support to Serendipity:
Getting Started
After a little research (see below) I decided to try Angular Gridster 2 (angular-gridster2). Angular Gridster 2 supports multi column and multi row layout, drag and move, drag and resize, drag and drop and more.
Step 1: Install Angular Gridster 2
I installed (the Angular 7 version of) Angular Gridster 2 using npm:
npm install angular-gridster2@7.2.0 --save
Step 2: Create a Dashboard Library
I used the Angular CLI to generate the scaffolding for a new library:
ng generate library dashboard --prefix=dashboard
Step 3: Import the Angular Gridster 2 module
I added the GridsterModule to the Dashboard module's imports array:
...
import { GridsterModule } from 'angular-gridster2';
@NgModule({
imports: [
...
GridsterModule
],
declarations: [ DashboardComponent ],
providers: [],
exports: [ DashboardComponent ],
entryComponents: []
})
export class DashboardModule {}
Step 4: Create a Dashboard Service
I generated the scaffolding for a new service:
ng generate service services/mocks/dashboard --project=dashboard
Note: To make it easier to switch between layout components and to use a familiar naming convention (i.e., Dashboard and Widget) I extended angular-gridster2's interfaces, for example:
export interface DashboardConfig extends GridsterConfig {}
export interface DashboardWidget extends DashboardItem {}
export interface Dashboard {
id?: string;
name?: string;
widgets?: Array<DashboardWidget>;
}
I updated the Dashboard service as follows:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Dashboard } from '../../../models/models';
@Injectable({
providedIn: 'root'
})
export class MockDashboardService {
private readonly DASHBOARDS = 'assets/data/dashboards.json';
constructor(protected httpClient: HttpClient) {}
public getDashboards(): Observable<Dashboard[]> {
return this.httpClient.get<Dashboard[]>(this.DASHBOARDS);
}
public getDashboard(dashboardId: string): Observable<Dashboard> {
return this.httpClient.get<Dashboard[]>(this.DASHBOARDS).pipe(
map((dashboards: Dashboard[]) =>
dashboards.find(dashboard => dashboard.id === dashboardId)));
}
}
[
{
"id": "4",
"name": "Sample Dashboard 4",
"widgets": [
{
"id": "1",
"name": "Timeline",
"component": "timeline",
"cols": 8,
"rows": 6,
"y": 0,
"x": 0
}
]
}
]
Step 5: Create a Dashboard Component
I used the Angular CLI to generate the scaffolding for a new component:
ng generate component components/dashboard --project=dashboard
I updated the Dashboard component's template as follows:
<gridster [options]="options">
<ng-container *ngFor="let item of items">
<gridster-item [item]="item">
<!-- Your content goes here -->
</gridster-item>
</ng-container>
</gridster>
And, I used the options
input property to configure the Dashboard component's Gridster instance:
...
import { MockDashboardService } from '../../services/mocks/dashboard/mock-dashboard.service';
@Component({
selector: 'dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
@Input() dashboardId: string;
public options: DashboardConfig;
public items: DashboardWidget[];
protected subscription: Subscription;
...
constructor(private dashboardService: MockDashboardService) {}
public ngOnInit() {
this.options = {
disablePushOnDrag: true,
draggable: { enabled: true },
gridType: GridType.Fit,
resizable: { enabled: true }
};
this.subscribe();
}
protected subscribe() {
this.subscription = this.dashboardService.getDashboard(this.dashboardId).subscribe(data => {
this.items = data.widgets;
});
}
}
Now all we need to do is add our new Dashboard directive to a host component and we're good to go:
<dashboard [dashboardId]="dashboardId"></dashboard>
Check out the demo on Firebase Hosting: Serendipity
What's Next
In the next post, I'll walk you through the steps I followed in order to add support for Dashboard Widgets and a Widget Tool Palette:
Source Code:
- GitHub: Serendipity
Research:
- GitHub: gridster.js
- GitHub: Angular Gridster - gridster-like widgets for AngularJS
- GitHub: gridstack.js
- GitHub: cube.js