قم بإنشاء لوحة تحكم سريعة الاستجابة باستخدام المواد الزاويّة والمخططات ng2

نشرت: 2022-03-10
ملخص سريع ↬ تعد المخططات في Angular 9 مولدات أكواد يمكنها إنشاء مكونات وأنماط في المشاريع باستخدام قوالب وتخطيطات محددة مسبقًا. في هذه المقالة ، تشرح Zara Cooper كيفية الاستفادة من المخططات في Angular Material و ng2-Charts لتقليل الوقت والعمل الذي يتم بذله في بناء لوحة القيادة إلى حد كبير.

غالبًا ما يكون إنشاء لوحة القيادة من نقطة الصفر أمرًا معقدًا للغاية. يجب عليك إنشاء أدوات لجمع البيانات حول العناصر ذات الأهمية. بمجرد جمع هذه البيانات ، يجب تقديمها بطريقة سهلة الفهم وذات مغزى للمستخدمين. إنه يتضمن تخطيطًا معقدًا للبيانات المراد تضمينها وكيفية عرضها بشكل فعال. بمجرد أن يكون لديك خطة ، فإن تنفيذ التصميم يعد مهمة ضخمة خاصة أنه يتضمن بناء مكونات متعددة.

باستخدام Angular Material و ng2-Charts ، يمكنك الاستفادة من المخططات لتقليل الجهد والوقت الذي قد تقضيه في بناء لوحة القيادة. تأتي المادة الزاويّة مع عدد من المخططات التي يمكنك استخدامها لإنشاء لوحة عدادات. وبالمثل ، توفر الرسوم البيانية ng2 مخططات لإنشاء مكونات متعددة للمخطط. في هذه المقالة ، سأوضح كيفية استخدام كل من الرسوم البيانية ng2 والمواد الزاويّة لإعداد لوحة القيادة بسرعة إلى حد ما.

مثال

لتوضيح كيفية إنشاء لوحة القيادة ، سنأخذ مثالاً لمتجر عبر الإنترنت يبيع سلعًا جلدية مثل الحقائب والمحافظ وحاملات المفاتيح وما إلى ذلك. يرغب صاحب المتجر في تتبع معلومات مثل من أين يأتي العملاء إلى متجرهم عبر الإنترنت ، وكيف تبيع منتجاتهم ، وكيف ترتبط مصادر حركة المرور بالمبيعات ، من بين أشياء أخرى.

سننشئ لوحة تحكم لعرض هذه المعلومات ومساعدة صاحب المتجر على تحليلها. ستحتوي لوحة المعلومات على أربع بطاقات موجزة صغيرة ، وأربعة أنواع مختلفة من المخططات ، وجدول يسرد أحدث الطلبات التي تم إجراؤها. ستعرض بطاقات الملخص الأربعة معلومات مثل إجمالي الإيرادات من المبيعات ومتوسط ​​قيمة الأمر وإجمالي عدد الطلبات وعدد العملاء العائدين. ستعرض المخططات عدد الوحدات المباعة لكل منتج ، والمبيعات حسب مصدر حركة المرور ، وجلسات المتجر عبر الإنترنت بمرور الوقت ، ومبيعات الأسبوع.

المتطلبات الأساسية

للمتابعة ، ستحتاج إلى تثبيت Angular CLI. إذا لم يكن مثبتًا لديك ، فيمكنك معرفة كيفية الحصول عليه من cli.angular.io. إذا كنت لا تبدأ من مشروع Angular موجود مسبقًا ، فأنت بحاجة إلى إنشاء واحد من خلال تشغيل ng new <your project name> . على سبيل المثال ، لإنشاء لوحة إدارة للمتجر المذكور أعلاه ، سنقوم بتشغيل:

 ng new store-admin-panel

يحتاج مشروعك أيضًا إلى مسارات مهيأة له. إذا كنت تبدأ من تطبيق جديد ، فحدد نعم عندما يُطلب منك إضافة وحدة توجيه Angular أثناء إعداد مشروعك أعلاه.

المزيد بعد القفز! أكمل القراءة أدناه ↓

أضف المواد الزاويّة والمخططات Ng2 إلى مشروعك

يتم شحن Angular Material بمخططات مختلفة لتوليد مجموعة متنوعة من المكونات المفيدة مثل دفاتر العناوين والأشجار والجداول والملاحة وما إلى ذلك. لإضافة Angular Material إلى مشروعك ، قم بتشغيل:

 ng add @angular/material

اختر سمة من الخيارات المتوفرة في المطالبات اللاحقة. بعد ذلك ، سيُطلب منك اختيار ما إذا كنت تريد إضافة أنماط الطباعة Angular Material والرسوم المتحركة للمتصفح. أنت لا تحتاج إلى هذه ويمكن فقط الرد لا.

بعد ذلك ، ستحتاج إلى تثبيت مخططات ng2. تتطلب مخططات ng2- charts.js كعنصر تبعية. لتثبيت مخططات ng2 ، قم بتنفيذ ما يلي:

 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 افتراضيًا.

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

إنشاء مكون التنقل

أولاً ، سنحتاج إلى إضافة مكون تنقل لمساعدة المستخدمين على المناورة عبر التطبيق بشكل مريح. يجب أن يحتوي التنقل على روابط إلى لوحة التحكم والصفحات الأخرى التي ستكون جزءًا من لوحة الإدارة. توفر المادة الزاوية مخططًا يقوم بإنشاء مكون تنقل. سنقوم بتسمية هذا المكون 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 chart. سيتم إنشاء مكون لوحة القيادة سريع الاستجابة. مرر الاسم المفضل للوحة القيادة إلى التخطيطي. في هذه الحالة ، دعنا dash .

 ng generate @angular/material:dashboard dash

لعرض لوحة المعلومات التي تم إنشاؤها حديثًا داخل مكون التنقل ، أضف مسارًا لها إلى جهاز التوجيه.

 // 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 لتصميم شبكة البطاقة سريعة الاستجابة هذه. تقوم الأداة المساعدة BreakpointObserver الخاصة بحزمة Layout بتقييم استعلامات الوسائط وإجراء تغييرات على واجهة المستخدم بناءً عليها. هناك العديد من نقاط التوقف المتاحة ولكن ضمن المكون الذي تم إنشاؤه ، يتم تلبية فئتين فقط. Breakpoints.Handset . سماعة الهاتف والاستفسارات الأخرى التي لا تتطابق معها. تحدد حزمة Layout 14 حالة من نقاط التوقف التي يمكنك استخدامها لتخصيص استجابة لوحة المعلومات.

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

بالعودة إلى لوحة القيادة ، نظرًا لأن أربع بطاقات موجزة وأربعة مخططات وجدول ستكون على لوحة القيادة ، نحتاج إلى تسع بطاقات في المجموع. Breakpoints.Handset ، مجموعة الهاتف ونقاط التوقف ، سيتم عرض مباريات Breakpoints.Tablet في شبكة من عمود واحد حيث:

  • ستمتد البطاقات الموجزة الأربعة على صف واحد.
  • ستمتد المخططات على صفين.
  • يمتد الجدول على أربعة صفوف.

غير Breakpoints.Handset ، مجموعة الهاتف وغير Breakpoints.Tablet ، سيتم عرض التطابقات اللوحية في أربعة أعمدة حيث:

  • ستمتد بطاقات الملخص الأربعة على صف واحد وعمود واحد.
  • ستمتد المخططات على صفين وعمودين.
  • يمتد الجدول على أربعة صفوف وأربعة أعمدة.

يجب أن تبدو شبيهة بلقطة الشاشة الموضحة أدناه في حالة عدم وجود Breakpoints.Handset Breakpoints.Tablet . في Breakpoints.Handset ، وسماعة الهاتف ونقاط التوقف ، Breakpoints.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.Handset ، مجموعة الهاتف ونقاط التوقف ، سيتم عرض مطابقات الاستعلام Breakpoints.Tablet في عمود واحد وتلك غير المتطابقة ستظهر في 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 ، استبدل قيم colspan و rowspan لعناصر mat-grid-tile وخاصية cols لعنصر mat-grid-list .

 <!--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 ، أنشئ المخططات الأربعة المختلفة. سنضعهم في مجلد يسمى المخططات. قم بتشغيل 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 إلى div s التي تضم عنصر canvas الرسم البياني في قوالب المخطط.

 <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; }

إضافة البيانات إلى الرسوم البيانية

تأتي مكونات المخطط المُنشأة مع بيانات نموذجية موصولة بالفعل. إذا كانت لديك خدمات موجودة مسبقًا توفر بياناتك الخاصة ، يمكنك إضافة هذه البيانات منها إلى مكونات المخطط. تأخذ المخططات تسميات لمحور س أو مجموعات بيانات أو بيانات ونوع مخطط وألوان ووسيلة إيضاح بالإضافة إلى خيارات التخصيص الأخرى. لتوفير البيانات والتسميات للمخططات ، قم بإنشاء خدمة تقوم بجلب البيانات من مصدر من اختيارك وإعادتها في نموذج تقبله المخططات. على سبيل المثال ، يتلقى AnnualSalesChartComponent مجموعة البيانات والتسميات الخاصة به من أسلوب SalesService getSalesByMonth والذي يُرجع مجموعة من المبيعات لكل شهر للسنة الحالية. يمكنك العثور على هذه الخدمة هنا والبيانات التي تعيدها هنا. قم بإدخال الخدمة كملكية خاصة إلى مُنشئ 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 التخطيطي (معاينة كبيرة)

قد يكون من الصعب جعل الجداول التي تحتوي على العديد من الأعمدة متجاوبة مع طرق عرض الهاتف والجهاز اللوحي. عند إضافة الجدول إلى بطاقة ، اجعله قابلاً للتمرير أفقيًا بحيث يمكن عرض جميع البيانات بشكل صحيح ولا يتم إعاقتها. يمكنك القيام بذلك عن طريق إضافة النمط أدناه إلى مكون الجدول الخاص بك:

 <!--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 من إحدى الخدمات. بالإضافة إلى ذلك ، سوف تحتاج إلى تعديل مصدر البيانات المُنشأة في الجدول الخاص بك لاستهلاك البيانات من الخدمة. للبدء ، قم بحقن الخدمة في مُنشئ فئة الجدول. لنأخذ مثالاً على جدول يسرد أحدث الطلبات للوحة القيادة هذه. للحصول على بيانات للجدول ، دعنا نقوم بحقن OrderService في مُنشئ OrdersTableComponent ، وتغيير تأكيد نوع 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 في مُنشئها. سيتعين علينا تعديل طرق connect destroy أيضًا. تقوم طريقة connect بتوصيل مصدر البيانات بالجدول وتحديث الجدول عند انبعاث عناصر بيانات جديدة من الدفق الذي يعيده ، في هذه الحالة ، مصفوفة أوامر يمكن ملاحظتها. يدمج ثابت dataMutations أول تحميل للبيانات ، وتقسيم الصفحات ، وفرز الأحداث في دفق واحد لكي يستهلكها الجدول. تتم معالجة ترقيم الصفحات والفرز من جانب خادم OrderService . لذلك نحتاج إلى تمرير الإزاحة وحجم الصفحة من ترقيم الصفحات وحقل الفرز النشط واتجاه الفرز لخاصية الفرز إلى طريقة getOrders في OrderService . يجب استخدام طريقة disconnect لإغلاق أي اتصالات تم إجراؤها وتحرير الموارد المعلقة في طريقة الاتصال.

 // 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() {} }

في قالب جدول الطلبات ، أدخل الأعمدة الجديدة واربط خاصية length لـ <mat-paginator> 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 ، قم بزيارة موقعهم المرتبط هنا.