آنلاین

Lifecycle و eventهای Router

Angular Router مجموعه کاملی از lifecycle hookها و eventها فراهم می‌کند که به شما اجازه می‌دهند به تغییرات navigation واکنش نشان دهید و در طول فرایند routing، logic سفارشی اجرا کنید.

Eventهای رایج router

Angular Router، navigation eventهایی emit می‌کند که می‌توانید برای دنبال کردن navigation lifecycle به آن‌ها subscribe کنید. این eventها از طریق observable مربوط به Router.events در دسترس‌اند. این بخش eventهای رایج routing lifecycle را برای navigation و error tracking پوشش می‌دهد، به‌ترتیب زمانی.

EventsDescription
NavigationStartوقتی navigation شروع می‌شود رخ می‌دهد و URL درخواست‌شده را شامل می‌شود.
RoutesRecognizedبعد از اینکه router مشخص کرد کدام route با URL match است رخ می‌دهد و اطلاعات route state را شامل می‌شود.
GuardsCheckStartphase مربوط به route guard را شروع می‌کند. Router، route guardهایی مثل canActivate و canDeactivate را ارزیابی می‌کند.
GuardsCheckEndکامل شدن ارزیابی guard را اعلام می‌کند. نتیجه، یعنی allowed یا denied، را شامل می‌شود.
ResolveStartphase مربوط به data resolution را شروع می‌کند. Route resolverها fetch کردن data را شروع می‌کنند.
ResolveEndData resolution کامل می‌شود. همه data لازم در دسترس قرار می‌گیرد.
NavigationEndevent نهایی وقتی navigation با موفقیت کامل می‌شود. Router، URL را به‌روزرسانی می‌کند.
NavigationSkippedوقتی router navigation را skip می‌کند رخ می‌دهد، مثلا navigation به همان URL.

موارد زیر error eventهای رایج هستند:

EventDescription
NavigationCancelوقتی router، navigation را cancel می‌کند رخ می‌دهد؛ اغلب به‌خاطر اینکه guard مقدار false برگردانده است.
NavigationErrorوقتی navigation fail می‌شود رخ می‌دهد؛ ممکن است به‌خاطر route نامعتبر یا error در resolver باشد.

برای فهرست همه lifecycle eventها، جدول کامل این راهنما را ببینید.

چطور به router eventها subscribe کنیم

وقتی می‌خواهید هنگام lifecycle eventهای مشخص navigation کد اجرا کنید، می‌توانید به router.events subscribe کنید و instance مربوط به event را بررسی کنید:

ts
// Example of subscribing to router events
import {Component, inject, signal, effect} from '@angular/core';
import {Event, Router, NavigationStart, NavigationEnd} from '@angular/router';

@Component(/* ... */)
export class RouterEvents {
  private readonly router = inject(Router);

  constructor() {
    // Subscribe to router events and react to events
    this.router.events.pipe(takeUntilDestroyed()).subscribe((event: Event) => {
      if (event instanceof NavigationStart) {
        // Navigation starting
        console.log('Navigation starting:', event.url);
      }
      if (event instanceof NavigationEnd) {
        // Navigation completed
        console.log('Navigation completed:', event.url);
      }
    });
  }
}

چطور routing eventها را debug کنیم

Debug کردن مشکل‌های router navigation بدون دیدن sequence eventها می‌تواند دشوار باشد. Angular یک debugging feature داخلی فراهم می‌کند که همه router eventها را در console log می‌کند و به شما کمک می‌کند navigation flow را بفهمید و تشخیص دهید مشکل کجا رخ می‌دهد.

وقتی لازم دارید sequence مربوط به Router event را inspect کنید، می‌توانید logging برای eventهای داخلی navigation را برای debugging فعال کنید. این کار را می‌توانید با پاس دادن یک configuration option، یعنی withDebugTracing()، انجام دهید که console logging دقیق برای همه routing eventها را فعال می‌کند.

ts
import {provideRouter, withDebugTracing} from '@angular/router';

const appRoutes: Routes = [];
bootstrapApplication(App, {
  providers: [provideRouter(appRoutes, withDebugTracing())],
});

برای اطلاعات بیشتر، docs رسمی مربوط به withDebugTracing را ببینید.

Use caseهای رایج

Router eventها قابلیت‌های کاربردی زیادی را در applicationهای واقعی ممکن می‌کنند. در اینجا چند pattern رایج را می‌بینید که با router eventها استفاده می‌شوند.

Loading indicatorها

هنگام navigation، loading indicator نمایش دهید:

ts
import {Component, inject} from '@angular/core';
import {Router} from '@angular/router';

@Component({
  selector: 'app-root',
  template: `
    @if (isNavigating()) {
      <div class="loading-bar">Loading...</div>
    }
    <router-outlet />
  `,
})
export class App {
  private router = inject(Router);
  isNavigating = computed(() => !!this.router.currentNavigation());
}

Analytics tracking

Page viewها را برای analytics track کنید:

ts
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {inject, DestroyRef, Service} from '@angular/core';
import {Router, NavigationEnd} from '@angular/router';

@Service()
export class AnalyticsService {
  private router = inject(Router);
  private destroyRef = inject(DestroyRef);

  startTracking() {
    this.router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
      // Track page views when URL changes
      if (event instanceof NavigationEnd) {
        // Send page view to analytics
        this.analytics.trackPageView(event.url);
      }
    });
  }

  private analytics = {
    trackPageView: (url: string) => {
      console.log('Page view tracked:', url);
    },
  };
}

Error handling

Navigation errorها را graceful مدیریت کنید و به کاربر feedback بدهید:

ts
import {Component, inject, signal} from '@angular/core';
import {
  Router,
  NavigationStart,
  NavigationError,
  NavigationCancel,
  NavigationCancellationCode,
} from '@angular/router';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-error-handler',
  template: `
    @if (errorMessage()) {
      <div class="error-banner">
        {{ errorMessage() }}
        <button (click)="dismissError()">Dismiss</button>
      </div>
    }
  `,
})
export class ErrorHandler {
  private router = inject(Router);
  readonly errorMessage = signal('');

  constructor() {
    this.router.events.pipe(takeUntilDestroyed()).subscribe((event) => {
      if (event instanceof NavigationStart) {
        this.errorMessage.set('');
      } else if (event instanceof NavigationError) {
        console.error('Navigation error:', event.error);
        this.errorMessage.set('Failed to load page. Please try again.');
      } else if (event instanceof NavigationCancel) {
        console.warn('Navigation cancelled:', event.reason);
        if (event.code === NavigationCancellationCode.GuardRejected) {
          this.errorMessage.set('Access denied. Please check your permissions.');
        }
      }
    });
  }

  dismissError() {
    this.errorMessage.set('');
  }
}

همه router eventها

برای reference، اینجا فهرست کامل همه router eventهای در دسترس در Angular آمده است. این eventها بر اساس category مرتب شده‌اند و به همان ترتیبی فهرست شده‌اند که معمولا در طول navigation رخ می‌دهند.

این eventها فرایند اصلی navigation را از شروع تا route recognition، guard checkها و data resolution دنبال می‌کنند. آن‌ها به شما دید می‌دهند که هر phase از navigation lifecycle چطور پیش می‌رود.

EventDescription
NavigationStartوقتی navigation شروع می‌شود رخ می‌دهد
RouteConfigLoadStartقبل از lazy loading یک route configuration رخ می‌دهد
RouteConfigLoadEndبعد از load شدن یک lazy-loaded route configuration رخ می‌دهد
RoutesRecognizedوقتی router، URL را parse می‌کند و routeها را تشخیص می‌دهد رخ می‌دهد
GuardsCheckStartدر شروع phase مربوط به guard رخ می‌دهد
GuardsCheckEndدر پایان phase مربوط به guard رخ می‌دهد
ResolveStartدر شروع phase مربوط به resolve رخ می‌دهد
ResolveEndدر پایان phase مربوط به resolve رخ می‌دهد

Activation eventها

این eventها در phase مربوط به activation رخ می‌دهند؛ زمانی که route componentها در حال instantiate و initialize شدن هستند. Activation eventها برای هر route در route tree اجرا می‌شوند، از جمله routeهای والد و فرزند.

EventDescription
ActivationStartدر شروع route activation رخ می‌دهد
ChildActivationStartدر شروع child route activation رخ می‌دهد
ActivationEndدر پایان route activation رخ می‌دهد
ChildActivationEndدر پایان child route activation رخ می‌دهد

Eventهای تکمیل navigation

این eventها نتیجه نهایی یک تلاش برای navigation را نشان می‌دهند. هر navigation دقیقا با یکی از این eventها تمام می‌شود و مشخص می‌کند navigation موفق بوده، cancel شده، fail شده یا skip شده است.

EventDescription
NavigationEndوقتی navigation با موفقیت تمام می‌شود رخ می‌دهد
NavigationCancelوقتی router، navigation را cancel می‌کند رخ می‌دهد
NavigationErrorوقتی navigation به‌خاطر error غیرمنتظره fail می‌شود رخ می‌دهد
NavigationSkippedوقتی router، navigation را skip می‌کند رخ می‌دهد، مثلا navigation به همان URL

Eventهای دیگر

یک event اضافه وجود دارد که بیرون از lifecycle اصلی navigation رخ می‌دهد، اما همچنان بخشی از event system مربوط به router است.

EventDescription
Scrollهنگام scrolling رخ می‌دهد

قدم بعدی

درباره route guardها و کارهای رایج router بیشتر یاد بگیرید.