Routing In ANGULAR 2+

 Routing In ANGULAR 2+

جدول المصطلحات:

          المصطلح                                                       

التعريف

Router

المكون المسؤول عن إدارة التنقل بين المكونات في تطبيق Angular

Routes

مصفوفة تعريف المسارات التي تربط URLs بالمكونات

RouterOutlet

الموجه الذي يعرض المكونات بناءً على المسار الحالي

RouterLink

الموجه لإنشاء روابط التنقل في القوالب

Route Parameters

قيم ديناميكية في المسار (مثل :id) تُمرر للمكونات

ما هو مصطلح التوجيه (Routing):

التوجيه (Routing) في Angular هو نظام يتيح إنشاء تطبيقات وحيدة الصفحة (SPA - Single Page Applications) حيث يتم التنقل بين المكونات المختلفة دون إعادة تحميل الصفحة. يتم التحكم في عرض المكونات بناءً على URL الحالي في المتصفح.

يتم توفير نظام التوجيه من خلال وحدة @angular/router والتي يجب استيرادها في التطبيق.

إعداد وتكوين التوجيه:

1. استيراد وحدة التوجيه

typescript

import { RouterModule, Routes } from '@angular/router';

2. تعريف المسارات (Routes)

المسار (Route) هو كائن JavaScript يحتوي على خاصيتين رئيسيتين:


  • path: سلسلة تحدد مسار URL

  • component: المكون الذي يجب عرضه لهذا المسار

typescript

// في app.module.ts

const routes: Routes = [

  { path: 'crisis-list', component: CrisisListComponent },

  { path: 'heroes-list', component: HeroesListComponent },

];

@NgModule({

  imports: [

    BrowserModule,

    RouterModule.forRoot(routes) // تسجيل المسارات

  ],

  exports: [RouterModule]

})

export class AppModule { }

3. إنشاء AppRoutingModule (أفضل ممارسة)

ينصح بإنشاء وحدة منفصلة للتوجيه:

typescript

// app-routing.module.ts

import { NgModule } from '@angular/core';

import { RouterModule, Routes } from '@angular/router';

import { CrisisListComponent } from './crisis-list.component';

import { HeroesListComponent } from './heroes-list.component';

const routes: Routes = [

  { path: 'crisis-list', component: CrisisListComponent },

  { path: 'heroes-list', component: HeroesListComponent },

];

@NgModule({

  imports: [RouterModule.forRoot(routes)],

  exports: [RouterModule]

})

export class AppRoutingModule { }


استخدام RouterOutlet:

<router-outlet> هو موجه (Directive) يعرض المكون المطابق للمسار الحالي.

مثال:

html

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

<app-header></app-header>


<!-- سيتم عرض المكون المطابق للمسار هنا -->

<router-outlet></router-outlet>


<app-footer></app-footer>

بدلاً من عرض جميع المكونات معاً:

html

<!-- ❌ غير صحيح -->

<app-crisis-list></app-crisis-list>

<app-heroes-list></app-heroes-list>

نستخدم:

html

<!-- ✅ صحيح -->

<router-outlet></router-outlet>

التنقل باستخدام RouterLink:

1. الروابط الأساسية

html

<nav>

  <a routerLink="/crisis-list">Crisis Center</a>

  <a routerLink="/heroes-list">Heroes</a>

</nav>

2. تحديد المسار النشط بـ RouterLinkActive

html

<nav>

  <a routerLink="/crisis-list" 

     routerLinkActive="active-link">

    Crisis Center

  </a>

  <a routerLink="/heroes-list" 

     routerLinkActive="active-link">

    Heroes

  </a>

</nav>

3. RouterLinkActive مع exact match

html

<a routerLink="/" 

   routerLinkActive="active"

   [routerLinkActiveOptions]="{ exact: true }">

  Home

</a>

مسارات خاصة:

1. إعادة التوجيه (Redirect)

typescript

const routes: Routes = [

  { path: '', redirectTo: '/heroes-list', pathMatch: 'full' },

  { path: 'crisis-list', component: CrisisListComponent },

  { path: 'heroes-list', component: HeroesListComponent },

];

  • redirectTo: المسار الذي سيتم التوجيه إليه

  • pathMatch:

    • 'full': يتطابق مع المسار الكامل

    • 'prefix': يتطابق مع بداية المسار

2. صفحة 404 (Wildcard Route)

typescript

const routes: Routes = [

  { path: '', redirectTo: '/heroes-list', pathMatch: 'full' },

  { path: 'crisis-list', component: CrisisListComponent },

  { path: 'heroes-list', component: HeroesListComponent },

  { path: '**', component: PageNotFoundComponent } // Wildcard - يجب أن يكون آخر مسار

];

ملاحظة مهمة: يجب أن يكون مسار Wildcard (**) دائماً في نهاية المصفوفة لأن Angular يطبق المسارات بالترتيب ويستخدم أول تطابق.

Route Parameters:

1. تعريف المسار مع بارامتر

typescript

const routes: Routes = [

  { path: 'heroes', component: HeroesListComponent },

  { path: 'hero/:id', component: HeroDetailComponent }, // :id هو بارامتر

];

2. التنقل مع بارامتر

html

<!-- في القالب -->

<a [routerLink]="['/hero', hero.id]">{{ hero.name }}</a>

typescript

// في المكون TypeScript

this.router.navigate(['/hero', heroId]);

3. قراءة البارامتر في المكون

الطريقة 1: Snapshot (للقيم الثابتة)

typescript

import { ActivatedRoute } from '@angular/router';


export class HeroDetailComponent implements OnInit {

  constructor(private route: ActivatedRoute) {}

  

  ngOnInit() {

    const id = this.route.snapshot.paramMap.get('id');

    // استخدام id...

  }

}

الطريقة 2: Observable (للقيم الديناميكية)

typescript

ngOnInit() {

  this.route.paramMap.subscribe(params => {

    const id = params.get('id');

    // يتم تحديث id عند تغيير المسار

  });

}

Query Parameters و Fragments:

1. تمرير Query Parameters

html

<a [routerLink]="['/search']" 

   [queryParams]="{ q: 'angular', page: 1 }">

  Search

</a>

typescript

// برمجياً

this.router.navigate(['/search'], {

  queryParams: { q: 'angular', page: 1 }

});

2. قراءة Query Parameters

typescript

this.route.queryParamMap.subscribe(params => {

  const searchQuery = params.get('q');

  const page = params.get('page');

});

3. Fragments (الروابط الداخلية)

html

<a [routerLink]="['/document']" fragment="section-2">

  Go to Section 2

</a>

Child Routes (المسارات الفرعية):

تعريف:

typescript

const routes: Routes = [

  {

    path: 'admin',

    component: AdminComponent,

    children: [

      { path: 'users', component: UsersComponent },

      { path: 'settings', component: SettingsComponent },

      { path: '', redirectTo: 'users', pathMatch: 'full' }

    ]

  }

];

في القالب:

html

<!-- admin.component.html -->

<h2>Admin Panel</h2>

<nav>

  <a routerLink="users">Users</a>

  <a routerLink="settings">Settings</a>

</nav>

<router-outlet></router-outlet> <!-- للمسارات الفرعية -->


Route Guards (حمايات المسارات):

1. CanActivate - للتحقق قبل الدخول للمسار

typescript

@Injectable({ providedIn: 'root' })

export class AuthGuard implements CanActivate {

  constructor(private authService: AuthService, private router: Router) {}

  

  canActivate(): boolean {

    if (this.authService.isLoggedIn()) {

      return true;

    }

    this.router.navigate(['/login']);

    return false;

  }

}

2. استخدام Guard

typescript

const routes: Routes = [

  { 

    path: 'dashboard', 

    component: DashboardComponent,

    canActivate: [AuthGuard] // حماية المسار

  }

];

Lazy Loading (التحميل الكسول)

تعريف:

typescript

const routes: Routes = [

  { 

    path: 'admin',

    loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)

  }

];

في AdminModule:

typescript

const adminRoutes: Routes = [

  { path: '', component: AdminDashboardComponent },

  { path: 'users', component: UsersComponent }

];


@NgModule({

  imports: [RouterModule.forChild(adminRoutes)],

  exports: [RouterModule]

})

export class AdminRoutingModule { }

أفضل الممارسات

  1. إنشاء AppRoutingModule منفصل عن AppModule

  2. ترتيب المسارات من الأكثر تحديداً إلى الأقل تحديداً

  3. استخدام Lazy Loading للمسارات الكبيرة

  4. تطبيق Route Guards للمسارات المحمية

  5. معالجة الأخطاء مع صفحة 404

  6. استخدام Relative Navigation داخل Child Routes

  7. فصل منطق التوجيه عن منطق الأعمال

مثال كامل متكامل

typescript

// app-routing.module.ts

import { NgModule } from '@angular/core';

import { RouterModule, Routes } from '@angular/router';

import { AuthGuard } from './auth.guard';


const routes: Routes = [

  { path: '', redirectTo: 'home', pathMatch: 'full' },

  { path: 'home', component: HomeComponent },

  { path: 'login', component: LoginComponent },

  

  // Lazy Loading

  { 

    path: 'products', 

    loadChildren: () => import('./products/products.module').then(m => m.ProductsModule) 

  },

  

  // Protected Route

  { 

    path: 'dashboard', 

    component: DashboardComponent,

    canActivate: [AuthGuard] 

  },

  

  // 404 Page

  { path: '**', component: PageNotFoundComponent }

];


@NgModule({

  imports: [RouterModule.forRoot(routes, {

    enableTracing: false, // للت debugging

    scrollPositionRestoration: 'enabled'

  })],

  exports: [RouterModule]

})

export class AppRoutingModule { }


Routing In ANGULAR 2+  Routing In ANGULAR 2+ بواسطة Remocolla Academy في مارس 22, 2026 تقييم: 5

ليست هناك تعليقات:

يتم التشغيل بواسطة Blogger.