يقدِّم لك هذا المقال التعليمي الأساسيات الموجودة في Angular من خلال السير معك في عملية بناء موقع تجارة إلكترونية مؤلف من قائمة من المنتجات، وسلة التسوق، ونموذج الدفع، كما يستخدِم هذا المقال تطبيقًا جاهزًا يمكنك معاينته وتعديله بصورة تفاعلية عن طريق StackBlitz دون الحاجة إلى إعداد بيئة عمل محلية، حيث تُعَدّ StackBlitz بيئة تطوير تعتمد على المتصفح وتمكِّنك من إنشاء وحفظ ومشاركة المشاريع باستخدام مجموعة متنوعة من التقنيات.
هذه المقال جزءٌ من سلسلة مقالات حول بناء تطبيق تجارة إلكترونية عبر Angular:
- ما هي Angular؟
- كيفية استعمال Angular في بناء تطبيقات الويب
- إضافة التنقل وإدارة البيانات في تطبيق Angular
- تهيئة بيئة تطبيقات Angular ونشرها على الويب
المتطلبات الأساسية
يجب أن يكون لديك فهم أساسي لما يلي لتحقيق أعلى إفادة من هذا المقال التعليمي:
تفاصيل التطبيق الذي سنبنيه
تُبنَى تطبيقات Angular بالاعتماد على المكوِّنات، إذ تمثِِّل هذه المكوِّنات اللبنات الأساسية لبناء واجهة المستخدِم والتي تتيح لك إعادة استخدام مجموعات كبيرة من وظائف واجهة المستخدِم، ويتألف المكوِّن من ثلاثة أشياء:
- صنف المكوِّن الذي يعالِج البيانات والوظائف.
- قالب HTML الذي يحدِّد واجهة المستخدِم.
- التنسيقات الخاصة بالمكوِّن التي تحدِّد الشكل والمظهر.
يوضح هذا الدليل كيفية بناء تطبيق باستخدام المكوِّنات التالية:
-
<app-root>
: المكوِّن الجذر الذي يُحمَّل أولًا والذي يمثِّل الحاوية للمكوِّنات الأخرى. -
<app-top-bar>
: اسم المتجر وزر الدفع. -
<app-product-list>
: قائمة المنتجات. -
<app-product-alerts>
- مكوِّن يحتوي على تنبيهات التطبيق.
البدء مع الملفات الأساسية للمشروع
ولِّد مشروع العينة الجاهزة في StackBlitz لإنشاء الملفات الأساسية التي سنتعامل معها، واتبع ما يلي لحفظ عملك:
- سجّل الدخول إلى StackBlitz.
- انسخ المشروع الذي ولَّدته.
- احفظ المشروع بصورة دورية.
يعرض جزء المعاينة الموجود على اليمين في StackBlitz حالة بدء تطبيق المثال، كما تعرض المعاينة منطقتين هما:
- My Store شريط علوي يحوي اسم المتجر وزر الدفع.
- Products ترويسة من أجل قائمة المنتجات.
يعرض جزء المشروع الموجود على اليسار الملفات المصدرية التي يتكون منها التطبيق، كما تتضمن ملفات البنية التحتية وملفات الضبط، في حين ينشئ StackBlitz ملفات أساسية وبيانات وهمية لك عندما تولِّد تطبيقات المثال في StackBlitz والتي تأتي مترافقة مع المقالات التعليمية، كما توجد جميع الملفات التي ستستخدمها خلال المقال التعليمي ضمن مجلد src
، ويمكنك الاطلاع على التوثيق الخاص بـ StackBlitz لمزيد من المعلومات حول استخدام StackBlitz.
إنشاء قائمة المنتجات
سنعمل في هذا القسم على تحديث التطبيق لعرض قائمة المنتجات، حيث سنستخدم بيانات المنتج المعرَّفة مسبقًا في ملف products.ts
والتوابع الموجودة في ملف product-list.component.ts
، كما سيرشدك هذا القسم خلال عملية تحرير ملف HTML والمعروف باسم القالب أيضًا.
بدايةً، افتح ملف القالب product-list.component.html
في مجلد product-list
وأضف موجِّهًا هيكليًا ngFor
للعنصر <div>
، كما يلي:
- الملف src/app/product-list/product-list.component.html:
<h2>Products</h2> <div *ngFor="let product of products"> </div>
سيتكرر العنصر <div>
من أجل كل منتج product
في قائمة المنتجات products
باستخدام ngFor*
، كما تشكّل الموجّهات الهيكلية Structural directives، أو تعيد تشكيل بنية DOM عن طريق إضافة العناصر وإزالتها ومعالجتها.
بعد ذلك أضف داخل العنصر <div>
العنوان <h3>
وضع فيه {{ product.name }}
الذي يمثل اسم المنتج وهو مثال عن سياق الإدراج في Angular، حيث يتيح لك الإدراج {{ }}
تصيير قيمة الخاصية على أساس نص.
- الملف src/app/product-list/product-list.component.html:
<h2>Products</h2> <div *ngFor="let product of products"> <h3> {{ product.name }} </h3> </div>
يُحدَّث جزء المعاينة لعرض اسم كل منتج في القائمة.
أضف العنصر <a>
حول {{ product.name }}
لربط اسم كل منتج بتفاصيله ثم اضبط العنوان ليصبح اسم المنتج باستخدام صياغة التربيط بين الخاصيات Property binding []
كما يلي:
- الملف src/app/product-list/product-list.component.html:
<h2>Products</h2> <div *ngFor="let product of products"> <h3> <a [title]="product.name + ' details'"> {{ product.name }} </a> </h3> </div>
مرّر مؤشر الفأرة فوق اسم منتج ما في جزء المعاينة لترى قيمة خاصية التربيط بالاسم، والتي تمثّل اسم المنتج بالإضافة إلى كلمة "تفاصيل". يتيح لك التربيط عن طريق الصياغة []
استخدام قيمة خاصية مُعرَّفة أو موجودة في القالب.
أضف توصيفات المنتجات عن طريق استخدام الموجِّه *ngIf
على عنصر <p>
، حيث ينشئ Angular عنصر <p>
فقط في حال كان المنتج الحالي يملك وصفًا.
- الملف src/app/product-list/product-list.component.html:
<h2>Products</h2> <div *ngFor="let product of products"> <h3> <a [title]="product.name + ' details'"> {{ product.name }} </a> </h3> <p *ngIf="product.description"> Description: {{ product.description }} </p> </div>
يعرض التطبيق الآن اسم ووصف كل منتج في القائمة، ولاحظ أنّ المنتج الأخير لا يملك فقرة وصف أي لا يملك قيمةً للخاصية description
وبالتالي لم تنشئ Angular عنصر <p>
له.
أخيرًا أضف زرًا حتى يتمكّن المستخدِمون من مشاركة المنتج واربط الحدث click
مع التابع ()share
في ملف product-list.component.ts
، ويكون التربيط بين الأحداث بوضع اسم الحدث بين قوسين ()
حول الحدث كما هو الحال في حدث (click)
ضمن عنصر <button>
.
- الملف src/app/product-list/product-list.component.html:
<h2>Products</h2> <div *ngFor="let product of products"> <h3> <a [title]="product.name + ' details'"> {{ product.name }} </a> </h3> <p *ngIf="product.description"> Description: {{ product.description }} </p> <button (click)="share()"> Share </button> </div>
يملك كل منتج الآن زر مشاركة Share.
تطلق عملية النقر على زر المشاركة تنبيهًا يخبرنا بأنه "شورِك المنتج!".
بهذا تكون قد استكشفت الآن الميزات الشائعة الاستخدام أثناء العمل في قوالب Angular.
تمرير البيانات إلى مكون ابن
تعرض حاليًا قائمة المنتجات اسم وتوصيف كل منتج، كما يعرِّف ProductListComponent
أيضًا خاصية products
التي تحتوي على بيانات مستورَدة لكل منتج من مصفوفة products
في products.ts
، وتكون الخطوة التالية هي إنشاء ميزة تنبيه جديدة تستخدِم بيانات المنتج من ProductListComponent
.
يتحقّق التنبيه من سعر المنتج، فإذا كان السعر أكبر من 700 دولار، سيعرض زر نبهني Notify Me الذي يتيح للمستخدِمين الاشتراك في الإشعارات عندما يُطرَح المنتج للبيع، كما سيرشدك هذا القسم خلال عملية إنشاء مكوِّن ابن ProductAlertsComponent
يمكنه تلقي البيانات من المكوِّن الأب ProductListComponent
.
بدايةً، انقر بزر الفأرة الأيمن على مجلد app
واستخدم المولد الخاص بـ Angular
لإنشاء مكون جديد يُسمّى product-alerts
.
ينشئ المولِّد ملفات البدء الأساسية لأجزاء المكوِّن الثلاثة:
- product-alerts.component.ts
- product-alerts.component.html
- product-alerts.component.css
افتح ملف product-alerts.component.ts
وستجد فيه مزخرفًا decorator باسم @Component()
يشير إلى أن الصنف الحالي هو مكوِّن، كما يوفِّر بيانات وصفية حوله بما في ذلك المحدِّد selector والقوالب templates والتنسيقات styles.
- الملف src/app/product-alerts/product-alerts.component.ts:
import { Component, OnInit } from '@angular/core'; @Component ({ selector: 'app-product-alerts', templateUrl: './product-alerts.component.html', styleUrls: ['./product-alerts.component.css'] }) export class ProductAlertsComponent implements OnInit { constructor() { } ngOnInit() { } }
تتمثَّل الميزات الرئيسية في @Component()
بما يلي:
-
يعرّف المحدد
selector
اسم المكون وقيمته هناapp-product-alerts
، كما تعارف مبرمجو Angular على بدء اسم المكون بالبادئة-app
متبوعة باسم المكوِّن. - تشير أسماء ملفات القوالب والتنسيقات إلى HTML وCSS للمكوِّن.
-
يصدِّر تعريف
@Component()
الصنفProductAlertsComponent
أيضًا والذي يعالِج وظائف المكوِّن.
ستورد Input
من @angular/core
أولًا لإعداد مكوِّن ProductAlertsComponent
لاستقبال بيانات المنتج.
- الملف src/app/product-alerts/product-alerts.component.ts:
import { Component, OnInit } from '@angular/core'; import { Input } from '@angular/core'; import { Product } from '../products';
أضف في تعريف الصنف ProductAlertsComponent
خاصيةً تسمى product
مع مزخرف @Input()
والذي يشير إلى تمرير قيمة الخاصية إلى المكوِّن الرئيسي ProductListComponent
.
- الملف src/app/product-alerts/product-alerts.component.ts:
export class ProductAlertsComponent implements OnInit { @Input() product!: Product; constructor() { } ngOnInit() { } }
افتح الملف product-alerts.component.html
واستبدل فقرة العنصر النائب بزر نبّهني Notify Me الذي يظهر في حال كان سعر المنتج أكثر من 700 دولار.
- الملف src/app/product-alerts/product-alerts.component.html:
<p *ngIf="product && product.price > 700"> <button>Notify Me</button> </p>
لاحظ أن المولد يضيف تلقائيًا الصنف ProductAlertsComponent
إلى الوحدة AppModule
ليكون متاحًا في كافة مكونات التطبيق:
import { ProductAlertsComponent } from './product-alerts/product-alerts.component'; @NgModule({ declarations: [ AppComponent, TopBarComponent, ProductListComponent, ProductAlertsComponent, ],
أضف المحدد <app-product-alerts>
إلى product-list.component.html
لعرض ProductAlertsComponent
على أساس ابن للمكوِّن ProductListComponent
، ومرِّر المنتج الحالي على أساس دخل إلى المكوِّن باستخدام التربيط عن طريق تربيط الخاصية property binding.
- الملف src/app/product-list/product-list.component.html:
<button (click)="share()"> Share </button> <app-product-alerts [product]="product"> </app-product-alerts>
يأخذ مكوِّن التنبيه الجديد الخاص بالمنتج منتجًا من قائمة المنتج على أساس دخل له، حيث يعرض أو يخفي عن طريقه زر نبهني Notify Me بناءً على قيمة سعر هذا المنتج، فسعر هاتف Phone XL مثلًا، هو أكثر من 700 دولار لذلك عُرِض زر نبهني Notify Me لهذا المنتج.
تمرير البيانات إلى المكون الرئيسي
يحتاج المكون الابن إلى التنبيه وإرسال البيانات إلى المكوِّن الأب لكي يعمل زر نبهني Notify Me، كما يحتاج ProductAlertsComponent
إلى إطلاق حدث عندما ينقر المستخدِم على نبهني Notify Me، في حين يحتاج ProductListComponent
إلى الاستجابة للحدث.
اقتباستوضيح: يتضمن مولد Angular في المكونات الحديثة بانيًا فارغًا
constructor()
وواجهةOnInit
وتابعngOnInit()
، وبما أنَّ الخطوات التالية لا تستخدِم ما سبق فقد حُذِفوا من شيفرات الأمثلة للاختصار.
أولًا، استورد Output
و EventEmitter
في الملف product-alerts.component.ts
من @angular/core
.
- الملف src/app/product-alerts/product-alerts.component.ts:
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { Product } from '../products';
ثانيًا، عرِّف خاصيةً تسمى notify
في صنف المكوِّن مع مزخرف @Output()
ونسخة من EventEmitter()
، هيِّئ المكوِّن ProductAlertsComponent
باستعمال @Output()
لكي تسمح لمكوِّن ProductAlertsComponent
بإطلاق حدث عندما تتغير قيمة الخاصية notify
.
- الملف src/app/product-alerts/product-alerts.component.ts:
export class ProductAlertsComponent { @Input() product: Product|undefined; @Output() notify = new EventEmitter(); }
ثالثًا، عدِّل زر نبهني Notify Me ضمن product-alerts.component.html
باستخدام التربيط مع الحدث من أجل استدعاء الدالة notify.emit()
.
- الملف src/app/product-alerts/product-alerts.component.html:
<p *ngIf="product && product.price > 700"> <button (click)="notify.emit()">Notify Me</button> </p>
رابعًا، عرِّف سلوكًا يحدث عندما ينقر المستخدِم على الزر، حيث يبدأ المكون الأب ProductListComponent
وليس المكون ProductAlertsComponent
بالعمل عندما يولِّد الابن الحدث. عرّف تابع onNotify()
ضمن product-list.component.ts
بطريقة مشابهة للتابعshare()
.
- الملف src/app/product-list/product-list.component.ts:
export class ProductListComponent { products = products; share() { window.alert('The product has been shared!'); } onNotify() { window.alert('You will be notified when the product goes on sale'); } }
خامسًا، حدِّث ProductListComponent
ليستقبل البيانات من ProductAlertsComponent
، واربط <app-product-alerts>
مع التابع onNotify()
الموجود في مكون قائمة المنتجات ضمن الملف product-list.component.html
، حيث ما يعرضه الزر نبهني Notify Me هو <app-product-alerts>
.
- الملف src/app/product-list/product-list.component.html:
<button (click)="share()"> Share </button> <app-product-alerts [product]="product" (notify)="onNotify()"> </app-product-alerts>
سادسًا، انقر على زر نبهني Notify Me لإطلاق التنبيه والذي يطبع رسالة "سوف تُعلَم عندما يُطرح المنتج للبيع" على المتصفح.
الخطوة التالية
أنشأتَ في هذا المقال تطبيقًا يمرّ على مجموعة من البيانات، كما أنشأتَ مكوِّنات مميزةً تتواصل مع بعضها، وسنكمل في المقال التالي استشكاف Angular وإنشاء التطبيق الخاص بك عبر مقال إضافة التنقل وإدارة البيانات في تطبيق Angular لإنشاء صفحة تفاصيل المنتج وقائمة المنتجات قبل أن ننتقل إلى خطوة نشر التطبيق على خادم الويب أو أي خادم تريد.
ترجمة -وبتصرف- للمقال Getting started with Angular من موقع angular.io الرسمي.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.