كيفية نقل البيانات في مكونات Angular الموجهة: دليل كامل بلغة TypeScript
\n\nكل مطور يبدأ العمل مع Angular، عاجلاً أم آجلاً، يواجه سؤالاً: "كيف أنقل البيانات من مكون إلى آخر عبر الموجه؟". على Stack Overflow، جمع هذا السؤال آلاف المشاهدات - وهذا ليس من قبيل الصدفة. على عكس المكونات العادية (parent-child)، حيث يكفي استخدام @Input() و @Output()، يضيف التوجيه في Angular تعقيداته الخاصة.
في هذه المقالة، سنستعرض 5 طرق مجربة لنقل البيانات في مكونات Angular الموجهة. ستعرف متى تستخدم كل طريقة، وستحصل على أمثلة جاهزة بلغة TypeScript. هيا بنا!
\n\nلماذا لا يمكن ببساطة نقل البيانات عبر @Input؟
\n\nيحاول العديد من المبتدئين القيام بذلك:
\n\n// ❌ هذا لا يعمل\n<router-outlet [someData]="data"></router-outlet>\n\nيقوم Angular Router بإنشاء المكونات ديناميكيًا. router-outlet هو توجيه (directive)، وليس عنصر قالب. لذلك نقل البيانات مباشرة عبر السمات (attributes) غير ممكن. ولكن هناك طرق بديلة - وهي أكثر ملاءمة!
الطريقة 1: استخدام حالة الموجه (Router State) (الأسهل)
\n\nالطريقة الأكثر بديهية هي نقل البيانات عبر كائن state أثناء التنقل. ظهرت هذه الطريقة في Angular 7+ وتعمل "مباشرة من الصندوق".
كيف تعمل
\n\nتقوم بتمرير كائن بالبيانات عند استدعاء router.navigate() أو عبر routerLink.
// المكون A - المرسل\nimport { Component } from '@angular/core';\nimport { Router } from '@angular/router';\n\n@Component({\n selector: 'app-user-list',\n template: `\n <button (click)="goToDetails()">فتح المستخدم</button>\n `\n})\nexport class UserListComponent {\n constructor(private router: Router) {}\n\n goToDetails() {\n this.router.navigate(['/user', 42], {\n state: { name: 'إيفان بيتروف', role: 'admin' }\n });\n }\n}\n\n// المكون B - المستلم\nimport { Component, OnInit } from '@angular/core';\nimport { Router } from '@angular/router';\n\n@Component({\n selector: 'app-user-details',\n template: `\n <div *ngIf="userData">\n <h2>{{ userData.name }}</h2>\n <p>الدور: {{ userData.role }}</p>\n </div>\n `\n})\nexport class UserDetailsComponent implements OnInit {\n userData: any;\n\n constructor(private router: Router) {\n // الحصول على البيانات من تاريخ التنقل\n this.userData = this.router.getCurrentNavigation()?.extras?.state;\n }\n\n ngOnInit() {\n // طريقة بديلة - عبر history.state\n if (!this.userData) {\n this.userData = history.state;\n }\n }\n}\n\nالإيجابيات والسلبيات
\n- \n
- ✅ سهولة التنفيذ \n
- ✅ البيانات غير مرئية في URL \n
- ✅ تعمل مع أي نوع من البيانات (كائنات، مصفوفات) \n
- ❌ البيانات تُفقد عند تحديث الصفحة \n
- ❌ لا تعمل عند الانتقال المباشر عبر URL \n
متى تستخدم: لنقل البيانات المؤقتة التي ليست حرجة عند إعادة التحميل (مثل رسائل الفلاش، الفلاتر).
\n\nالطريقة 2: محلل المسار (Route Resolver) (لتحميل البيانات مسبقًا)
\n\nإذا كنت بحاجة لتحميل البيانات قبل أن يظهر المكون، استخدم Angular Resolver. وهي خدمة تقوم بحل (resolve) البيانات قبل تفعيل المسار.
\n\nإنشاء Resolver
\n\n// user.resolver.ts\nimport { Injectable } from '@angular/core';\nimport { Resolve, ActivatedRouteSnapshot } from '@angular/router';\nimport { Observable, of } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class UserResolver implements Resolve<any> {\n resolve(route: ActivatedRouteSnapshot): Observable<any> {\n const userId = route.paramMap.get('id');\n // وم