使用 Angular Material 和 ng2-Charts 創建響應式儀表板

已發表: 2022-03-10
快速總結↬ Angular 9 中的 Schematics 是代碼生成器,可以使用預定的模板和佈局在項目中創建組件和模式。 在本文中,Zara Cooper 解釋瞭如何利用 Angular Material 和 ng2-charts 中的示意圖來大幅減少構建儀表板的時間和工作量。

從頭開始創建儀表板通常非常複雜。 您必須創建工具來收集有關感興趣項目的數據。 一旦收集到這些數據,就必須以易於理解和有意義的方式向您的用戶呈現。 它涉及對包含哪些數據以及如何有效顯示數據的複雜規劃。 一旦制定了計劃,實施設計就是一項艱鉅的任務,尤其是因為它涉及構建多個組件。

使用 Angular Material 和 ng2-charts,您可以利用原理圖來減少構建儀表板的工作量和時間。 Angular Material 附帶了許多可用於生成儀表板的示意圖。 同樣,ng2-charts 提供了用於生成多個圖表組件的示意圖。 在本文中,我將說明如何使用 ng2-charts 和 Angular Material 來相當快速地設置儀表板。

一個例子

為了說明如何構建儀表板,我們將以銷售包、錢包、鑰匙扣等皮具的在線商店為例。 店主希望跟踪信息,例如客戶從哪裡來到他們的在線商店、他們的產品如何銷售、流量來源與銷售的關係等等。

我們將構建一個儀表板來顯示這些信息並幫助店主對其進行分析。 儀表板將包含四個小摘要卡、四種不同類型的圖表和一個列出最近訂單的表格。 四個匯總卡將顯示銷售總收入、平均訂單價值、訂單總數和回頭客數量等信息。 這些圖表將顯示每種產品的銷售量、流量來源的銷售額、一段時間內的在線商店會話以及一周的銷售額。

先決條件

要繼續進行,您需要安裝 Angular CLI。 如果您沒有安裝它,您可以在 cli.angular.io 找到如何獲取它。 如果您不是從預先存在的 Angular 項目開始,則需要通過運行ng new <your project name>來生成一個。 例如,要為上述商店創建一個管理面板,我們將運行:

 ng new store-admin-panel

您的項目還需要為其配置路由。 如果您是從一個新應用程序開始,請在上面的項目設置過程中提示您是否添加 Angular Routing 模塊時選擇

跳躍後更多! 繼續往下看↓

將 Angular Material 和 Ng2-Charts 添加到您的項目中

Angular Material 附帶了各種原理圖,用於生成各種有用的組件,如地址簿、樹、表格、導航等。 要將 Angular Material 添加到您的項目中,請運行:

 ng add @angular/material

從後續提示中提供的選項中選擇一個主題。 接下來,系統會提示您選擇是否添加 Angular Material 排版樣式和瀏覽器動畫。 你不需要這些,可以回答不。

接下來,您需要安裝 ng2-charts。 ng2-charts 需要chart.js作為依賴項。 要安裝 ng2-charts 運行:

 npm install ng2-charts --save

然後安裝charts.js:

 npm install chart.js --save

要訪問圖表,請將ChartsModule添加到AppModule的導入中。

 import { ChartsModule } from 'ng2-charts'; @NgModule({ imports: [ … ChartsModule, … ] })

最後,安裝 ng2-charts 示意圖作為開發依賴項,因為默認情況下它們不附帶 ng2-charts。

 npm install --save-dev ng2-charts-schematics

生成導航組件

首先,我們需要添加一個導航組件來幫助用戶舒適地瀏覽應用程序。 導航應該包含指向儀表板和其他頁面的鏈接,這些頁面將成為管理面板的一部分。 Angular 材料提供了生成導航組件的示意圖。 我們將此組件命名為nav 。 通過運行以下命令完成向應用程序添加側導航:

 ng generate @angular/material:navigation nav

要鏈接導航中的其他路由,請使用routerLink指令並根據用戶所在的路由更改工具欄中的頁面名稱。

 // nav.component.ts ... menuItems = ['dashboard', 'sales', 'orders', 'customers', 'products'];
 <!--nav.component.html--> ... <mat-nav-list> <a *ngFor="let item of menuItems" mat-list-item [routerLink]="'/'+item"> {{item | titlecase}} </a> ...

要查看此組件,請將其添加到app.component.html

 <!--app.component.html--> <app-nav></app-nav>

這就是NavComponent的樣子。

導航組件
導航組件(大預覽)

由於導航將與其他組件一起顯示,因此向其添加router-outlet將有助於在其他不同組件之間切換。 在nav.component.html模板中,在關閉</mat-toolbar>之後,將<!-- Add Content Here -->註釋替換為<router-outlet></router-outlet>

 <!--nav.component.html--> <mat-sidenav-container> ... <mat-sidenav-content> <mat-toolbar> ... </mat-toolbar> <router-outlet></router-outlet> </mat-sidenav-content> </mat-sidenav-container>

在本文後面的屏幕截圖中,將省略此導航組件,以更好地突出顯示我們將在本教程中生成的儀表板。 如果您在構建此儀表板時跟隨,導航仍將如上圖所示顯示在您的瀏覽器中,其中包含儀表板。

生成儀表板

儀表板最重要的部分是它的佈局。 它需要容納前面提到的所有組件,並在不同設備上顯示時做出響應。 要生成儀表板佈局,您需要運行@angular/material:dashboard示意圖。 它將生成一個響應式儀表板組件。 將儀表板的首選名稱傳遞給原理圖。 在這種情況下,我們將其命名為dash

 ng generate @angular/material:dashboard dash

要在 nav 組件中查看新生成的儀表板,請將其添加到路由器的路由。

 // app-routing.module.ts import { DashComponent } from './dash/dash.component'; const routes: Routes = [{ path: 'dashboard', component: DashComponent }]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] })

完成後,要查看結果,運行npm start並前往localhost:4200/dashboard 。 你應該看到這個:

生成的儀表板組件
生成的儀表板組件(大預覽)

原理圖在模板中生成四張卡片,並將它們顯示在響應式網格中。 Angular Material CDK 使用Layout包來設置這個響應式卡片網格的樣式。 Layout包的BreakpointObserver實用程序評估媒體查詢並根據它們進行 UI 更改。 有各種可用的斷點,但在生成的組件中,只滿足兩個類別。 Breakpoints.Handset和其他不匹配的查詢。 Layout包指定了 14 個斷點狀態,您可以使用它們來自定義儀表板的響應能力。

 // dashboard.component.js ... cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe( map(({ matches }) => { if (matches) { ... } ... }) );

回到儀表板,由於儀表板上將有四張摘要卡、四張圖表和一張表格,我們總共需要九張卡片。 Breakpoints.HandsetBreakpoints.Tablet匹配項將顯示在單列網格中,其中:

  • 四張摘要卡將跨越一排。
  • 圖表將跨越兩行。
  • 該表將跨越四行。

Breakpoints.Handset和非Breakpoints.Tablet匹配項將顯示在四列中,其中:

  • 四個摘要卡將跨越一行一列。
  • 圖表將跨越兩行和兩列。
  • 該表將跨越四行四列。

在非Breakpoints.Handset和非Breakpoints.Tablet匹配中,它應該類似於下面的屏幕截圖。 在Breakpoints.HandsetBreakpoints.Tablet匹配時,所有內容都將僅顯示在一列中。

帶有附加卡的儀表板組件
帶有附加卡片的儀表板組件(大預覽)

創建卡片組件

在儀表板組件中,所有卡片都是通過迭代生成的。 為了防止重複,在添加所有新組件時,我們將創建一個可重用的卡片組件。 卡片組件將接受標題作為輸入,並使用ng-content動態添加其餘內容。 要創建卡片組件,請運行:

 ng gc card -m app --style css

從儀表板組件模板中,我們只需將<mat-card>標記中包含的標記放入卡片模板中:

 <!--card.component.html--> <mat-card class="dashboard-card"> <mat-card-header> <mat-card-title> {{title}} <button mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu"> <mat-icon>more_vert</mat-icon> </button> <mat-menu #menu="matMenu" xPosition="before"> <button mat-menu-item>Expand</button> <button mat-menu-item>Remove</button> </mat-menu> </mat-card-title> </mat-card-header> <mat-card-content class="dashboard-card-content"> <ng-content></ng-content> </mat-card-content> </mat-card>

要將標題作為輸入添加到卡片:

 // card.component.ts import { Component, Input } from '@angular/core'; ... export class CardComponent{ @Input() title: string; ... }

設置卡片樣式:

 /*card.component.css*/ .more-button { position: absolute; top: 5px; right: 10px; } .dashboard-card { position: absolute; top: 15px; left: 15px; right: 15px; bottom: 15px; } .dashboard-card-content { text-align: center; flex-grow: 1; display: flex; flex-direction: column; align-items: center; max-height: 100%; justify-content: center; align-items: stretch; } mat-card { display: flex; flex-direction: column; }

將卡片添加到儀表板

由於儀表板元素將單獨添加而不是通過迭代添加,因此需要修改儀表板組件以解決此問題。 在dashboard.component.ts中,移除cards屬性並將其替換為cardLayout屬性。 cardLayout變量將定義材料網格列表的列數以及每個儀表闆卡將跨越多少行和列。 Breakpoints.HandsetBreakpoints.Tablet查詢匹配將顯示在 1 列中,不匹配的將顯示在 4 列中。

 // dashboard.component.js ... cardLayout = this.breakpointObserver.observe(Breakpoints.Handset).pipe( map(({ matches }) => { if (matches) { return { columns: 1, miniCard: { cols: 1, rows: 1 }, chart: { cols: 1, rows: 2 }, table: { cols: 1, rows: 4 }, }; } return { columns: 4, miniCard: { cols: 1, rows: 1 }, chart: { cols: 2, rows: 2 }, table: { cols: 4, rows: 4 }, }; }) ); ...

dash.component.html模板中,替換mat-grid-tile元素的colspanrowspan值以及 mat mat-grid-list元素的cols屬性。

 <!--dash.component.html--> <div class="grid-container"> <h1 class="mat-h1">Dashboard</h1> <mat-grid-list cols="{{ ( cardLayout | async )?.columns }}" rowHeight="200px"> <!--Mini Cards--> <mat-grid-tile *ngFor="let i of [1, 2, 3, 4]" [colspan]="( cardLayout | async )?.miniCard.cols" [rowspan]="( cardLayout | async )?.miniCard.rows"> <app-card title="Card {{i}}"><div>Mini Card Content Here</div></app-card> </mat-grid-tile> <!--Charts--> <mat-grid-tile *ngFor="let i of [5, 6, 7, 8]" [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Card {{i}}"><div>Chart Content Here</div></app-card> </mat-grid-tile> <!--Table--> <mat-grid-tile [colspan]="( cardLayout | async )?.table.cols" [rowspan]="( cardLayout | async )?.table.rows"> <app-card title="Card 9"><div>Table Content Here</div></app-card> </mat-grid-tile> </mat-grid-list> </div>

儀表板最終看起來與上面鏈接的最新屏幕截圖完全相同。

生成圖表

儀表板需要的四個圖表是:

  • 按銷售單位劃分的產品雷達圖。
  • 按流量來源的銷售額餅圖。
  • 在線商店會話的條形圖。
  • 全年銷售折線圖。

與創建儀表板類似,生成圖表組件涉及運行原理圖。 使用 ng2-charts 原理圖,生成四個不同的圖表。 我們將它們放在一個名為charts 的文件夾中。 運行ng generate ng2-charts-schematics:<chart type> <chart name>

 ng generate ng2-charts-schematics:radar charts/product-sales-chart ng generate ng2-charts-schematics:pie charts/sales-traffic-chart ng generate ng2-charts-schematics:line charts/annual-sales-chart ng generate ng2-charts-schematics:bar charts/store-sessions-chart

運行這些命令後,將生成所有四個圖表組件並填充準備顯示的示例數據。 根據您要顯示的數據,選擇最適合您的數據可視化需求的圖表。 對於上面生成的每個圖表,將chartContainer類添加到圖表模板中包含canvas元素的div中。

 <div class="chartContainer"> <canvas baseChart width="400" height="400"> ...

接下來,將此樣式添加到styles.css以便所有圖表組件都可以訪問它們。

 /*styles.css*/ ... .chartContainer canvas { max-height: 250px; width: auto; } .chartContainer{ height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; }

向圖表添加數據

生成的圖表組件附帶已插入的示例數據。如果您有提供自己數據的預先存在的服務,您可以將這些數據從它們添加到圖表組件中。 圖表採用 x 軸、數據或數據集、圖表類型、顏色、圖例以及其他自定義選項的標籤。 要為圖表提供數據和標籤,請創建一個服務,該服務將從您選擇的來源獲取數據並以圖表接受的形式返回數據。 例如, AnnualSalesChartComponentSalesServicegetSalesByMonth方法接收其數據集和標籤,該方法返回當年每個月的銷售額數組。 您可以在此處找到此服務並在此處找到它返回的數據。 將服務作為私有屬性注入到AnnualSalesChartComponent構造函數中。 在ngOnInit生命週期掛鉤中調用從服務返回所需圖表數據的方法。

 // annual-sales-chart.component.ts import { SalesService } from 'src/app/sales/sales.service'; ... export class AnnualSalesChartComponent implements OnInit { public salesChartData: ChartDataSets[] = [ { data: [], label: 'Total Sales' }, ]; public salesChartLabels: Label[] = []; ... constructor(private salesService: SalesService) { } ngOnInit() { this.salesService.getSalesByMonth().subscribe({ next: salesItems => { salesItems.forEach(li => { this.salesChartData[0].data.push(li.revenue); this.salesChartLabels.push(li.month); }); }, ... }); } }

將圖表添加到儀表板

下一步涉及在dash.component.html圖表添加到儀表板。 看起來是這樣的:

 <!--dash.component.html--> ... <!--Charts--> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Monthly Revenue"> <app-annual-sale-chart></app-annual-sale-chart> </app-card> </mat-grid-tile> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Product Sales"> <app-product-sales-chart></app-product-sales-chart> </app-card> </mat-grid-tile> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Sales by Traffic Source"> <app-sales-traffic-chart></app-sales-traffic-chart> </app-card> </mat-grid-tile> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Online Store Sessions by Traffic Source"> <app-store-sessions-chart></app-store-sessions-chart> </app-card> </mat-grid-tile> ...

這就是生成的響應式儀表板的樣子。

帶有圖表的儀表板
帶有圖表的儀表板(大預覽)

生成表

我們將添加一個訂單表,為店主提供最近下達的訂單及其狀態的概覽。 要生成訂單表組件,請運行原理圖:

 ng generate @angular/material:table orders-table

這將生成一個看起來像這樣的表格組件。

由 Angular Material 原理圖生成的表格
由 Angular Material 原理圖生成的表格(大預覽)

具有許多列的表格可能難以響應手機和平板電腦的視圖。 將表格添加到卡片時,使其可水平滾動,以便所有數據都可以正常查看且不受阻礙。 您可以通過將以下樣式添加到表格組件來做到這一點:

 <!--table.component.html--> <div class="mat-elevation-z8 small-table"> <table mat-table class="full-width-table" matSort aria-label="Elements"> ...
 /*table.component.css*/ ... .small-table{ overflow-x: scroll !important; }

要將表格添加到破折號組件:

 <!-- dashboard.component.html> ... <mat-grid-tile [colspan]="( cardLayout | async )?.table.cols" [rowspan]="( cardLayout | async )?.table.rows"> <app-card title="Latest Orders"> <app-orders-table></app-orders-table> </app-card> </mat-grid-tile> ...

向表中添加數據

與圖表一樣,您可以通過服務的ngOnInit方法將數據添加到表中。 此外,您將需要修改表的生成數據源以使用服務中的數據。 首先,在表的類構造函數中註入服務。 讓我們以列出此儀表板最新訂單的表格為例。 要獲取表格的數據,讓我們在OrdersTableComponent構造函數中註入OrderService ,更改表格視圖子視圖的MatTable類型斷言,並修改顯示的列列表以反映訂單界面。 如果您對添加到表中的數據感興趣,可以在此處找到。 最後一件事涉及獲取可用於在表的<mat-paginator>中設置總數的數據項的總長度。

 // orders-table.component.ts import { OrderService } from '../orders.service'; import { Order } from '../order'; ... export class OrdersTableComponent implements AfterViewInit, OnInit { ... @ViewChild(MatTable) table: MatTable ; dataLength: number; displayedColumns = [ "id", "date", "name", "status", "orderTotal", "paymentMode", ]; ... constructor(private orderService: OrderService){} ngOnInit() { this.datasource = new OrdersTableDataSource(this.orderService); this.orderService.getOrderCount().subscribe({ next: orderCount => { this.dataLength = orderCount; }, ... }); } ... } // orders-table.component.ts import { OrderService } from '../orders.service'; import { Order } from '../order'; ... export class OrdersTableComponent implements AfterViewInit, OnInit { ... @ViewChild(MatTable) table: MatTable ; dataLength: number; displayedColumns = [ "id", "date", "name", "status", "orderTotal", "paymentMode", ]; ... constructor(private orderService: OrderService){} ngOnInit() { this.datasource = new OrdersTableDataSource(this.orderService); this.orderService.getOrderCount().subscribe({ next: orderCount => { this.dataLength = orderCount; }, ... }); } ... }

接下來,我們需要修改OrdersTableDataSource類以在其構造函數中接受OrderService作為參數。 我們還必須修改它的connectdestroy方法。 connect方法將數據源連接到表,並在從它返回的流(在本例中為可觀察的訂單數組)發出新數據項時更新表。 dataMutations常量將第一個數據加載、分頁和排序事件組合到一個流中供表使用。 分頁和排序由OrderService服務器端處理。 所以我們需要將分頁器的偏移量和頁面大小以及排序屬性的活動排序字段和排序方向傳遞給OrderServicegetOrders方法。 disconnect方法應該用於關閉任何已建立的連接並釋放在 connect 方法中佔用的資源。

 // orders-table.datasource.ts ... export class OrdersTableDataSource extends DataSource<Order> { paginator: MatPaginator; sort: MatSort; constructor(private orderService: OrderService) { super(); } connect(): Observable<Order[]> { const dataMutations = [ of('Initial load'), this.paginator.page, this.sort.sortChange ]; return merge(...dataMutations).pipe(mergeMap(() => { return this.orderService.getOrders( this.paginator.pageIndex * this.paginator.pageSize, this.paginator.pageSize, this.sort.active, this.sort.direction ); })); } disconnect() {} }

在訂單表模板中,插入新列並將<mat-paginator>length屬性綁定到dataLength屬性。 對於狀態列,使用<mat-chip>元素可以更好地顯示訂單狀態。 要訪問<mat-chip> ,請將MatChipsModule作為導入添加到AppModule

 <!-- orders-table.component.html --> <div class="mat-elevation-z8"> <table mat-table class="full-width-table" matSort aria-label="Elements"> <!-- Id Column --> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th> <td mat-cell *matCellDef="let row">{{row.id}}</td> </ng-container> <!-- Date Column --> <ng-container matColumnDef="date"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th> <td mat-cell *matCellDef="let row">{{row.date | date }}</td> </ng-container> <!-- Name Column --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th> <td mat-cell *matCellDef="let row">{{row.name}}</td> </ng-container> <!-- Order Total Column --> <ng-container matColumnDef="orderTotal"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Order Total</th> <td mat-cell *matCellDef="let row">{{row.orderTotal | currency}}</td> </ng-container> <!-- Payment Mode Column --> <ng-container matColumnDef="paymentMode"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Mode</th> <td mat-cell *matCellDef="let row">{{row.paymentMode}}</td> </ng-container> <!-- Status Column --> <ng-container matColumnDef="status"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th> <td mat-cell *matCellDef="let row"> <mat-chip-list> <mat-chip color="{{ row.status == 'delivered' ? 'primary' : ( row.status == 'shipped' ? 'accent' : 'warn' ) }}" selected> {{row.status}} </mat-chip> </mat-chip-list> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator #paginator [length]="dataLength" [pageIndex]="0" [pageSize]="5" [pageSizeOptions]="[5, 10, 15, 20]"> </mat-paginator> </div>

將數據添加到表中後,儀表板將如下所示:

帶有圖表和表格的儀表板
帶有圖表和表格的儀表板(大預覽)

創建迷你卡組件

完成儀表板剩下的就是填充位於頂部的四張小卡片。 將較小的摘要卡作為儀表板的一部分可以輕鬆突出顯示不需要整個圖表或表格的簡短信息。 在此示例中,四張迷你卡片將顯示總銷售額、平均訂單價值、訂單總數以及當天光顧商店的回頭客數量。 這只是一個例子。 這些迷你卡片無法像導航、儀表板佈局、圖表和表格那樣生成。 他們沒有原理圖。 下面我們將簡要介紹如何創建它們。 雖然我們將添加特定於示例的數據,但您可以添加任何您想要的內容或決定完全取消它們。 首先,生成mini-card組件,運行:

 ng gc mini-card -m app --style css

您可以在此處找到鏈接的組件的模板及其樣式。 該組件有八個輸入屬性,您可以在此處了解如何添加它們。 要向迷你卡組件獲取數據,請在DashComponent構造函數中註入為它們提供數據的服務。 將從服務接收到的數據分配給DashComponent的屬性。 在本例中,我們將從StoreSummaryService獲取數據並將其分配給miniCardData屬性。 這是如何做:

 // dash.component.ts export class DashComponent implements OnInit{ ... miniCardData: StoreSummary[]; constructor(private breakpointObserver: BreakpointObserver, private summaryService: StoreSummaryService) {} ngOnInit() { this.summaryService.getStoreSummary().subscribe({ next: summaryData => { this.miniCardData = summaryData; } }); } }

要將mini-cards添加到儀表板組件並使用來自服務的數據填充它們:

 <!--dash.component.html--> ... <!--Mini Cards--> <mat-grid-tile *ngFor="let mc of miniCardData" [colspan]="( cardLayout | async )?.miniCard.cols" [rowspan]="( cardLayout | async )?.miniCard.rows"> <app-mini-card [title]="mc.title" [textValue]="mc.textValue" [value]="mc.value" [color]="mc.color" [percentValue]="mc.percentValue"></app-mini-card> </mat-grid-tile> ...

下面的屏幕截圖是填充了迷你卡的儀表板的樣子。

帶有圖表、表格和迷你卡片的儀表板
帶有圖表、表格和迷你卡片的儀表板。 (大預覽)

放在一起

最後,儀表板組件模板應包含:

 <!-- dashboard.component.html --> <div class="grid-container"> <h1 class="mat-h1">Dashboard</h1> <mat-grid-list cols="{{ ( cardLayout | async )?.columns }}" rowHeight="200px"> <!--Mini Cards--> <mat-grid-tile *ngFor="let mc of miniCardData" [colspan]="( cardLayout | async )?.miniCard.cols" [rowspan]="( cardLayout | async )?.miniCard.rows"> <app-mini-card [icon]="mc.icon" [title]="mc.title" [value]="mc.value" [color]="mc.color" [isIncrease]="mc.isIncrease" duration="since last month" [percentValue]="mc.percentValue" [isCurrency]="mc. isCurrency"></app-mini-card> </mat-grid-tile> <!--Charts--> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Monthly Revenue"> <app-annual-sale-chart></app-annual-sale-chart> </app-card> </mat-grid-tile> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Product Sales"> <app-product-sales-chart></app-product-sales-chart> </app-card> </mat-grid-tile> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Sales by Traffic Source"> <app-sales-traffic-chart></app-sales-traffic-chart> </app-card> </mat-grid-tile> <mat-grid-tile [colspan]="( cardLayout | async )?.chart.cols" [rowspan]="( cardLayout | async )?.chart.rows"> <app-card title="Online Store Sessions by Traffic Source"> <app-store-sessions-chart></app-store-sessions-chart> </app-card> </mat-grid-tile> <!--Table--> <mat-grid-tile [colspan]="( cardLayout | async )?.table.cols" [rowspan]="( cardLayout | async )?.table.rows"> <app-card title="Latest Orders"> <app-orders-table></app-orders-table> </app-card> </mat-grid-tile> </mat-grid-list> </div>

這是生成的儀表板包含的內容。

完成的儀表板
完成的儀表板(大預覽)

結論

創建儀表板涉及大量工作和計劃。 加快構建速度的一種方法是使用 Angular Material 和 ng2-charts 提供的各種示意圖。 使用這些示意圖,運行命令將生成一個完整的組件,並且可以使儀表板快速啟動並運行。 這讓您有更多時間專注於創建數據服務並將它們添加到儀表板組件中。

如果您想了解更多關於 Angular Material 提供的一些原理圖,請訪問 material.angular.io,對於 ng2-charts 提供的那些,請訪問此處鏈接的他們的網站。