Router Guards & Resolvers

5 questions found

What is a route guard in Angular, and what is it commonly used for?

Beginner
A route guard is a function that runs before a route is activated, deciding whether navigation should be allowed to continue, redirected elsewhere, or blocked entirely. A very common use is protecting pages that require a user to be logged in, redirecting anonymous visitors to a login page instead.
export const authGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  const router = inject(Router);
  if (authService.isLoggedIn()) return true;
  router.navigate(['/login']);
  return false;
};

{ path: 'dashboard', component: DashboardComponent, canActivate: [authGuard] }
Real-world example A banking app automatically redirects any visitor who is not logged in away from the account dashboard page and back to the login screen, using a route guard applied to that specific protected route.

Common follow-ups: How would you also remember the page a user was trying to visit, so they land there after logging in?;What is the difference between canActivate and canActivateChild?

Authentication;Services & Dependency Injection

What is the canDeactivate guard used for, and how would you use it to warn a user about unsaved changes?

Intermediate
The canDeactivate guard runs before a user navigates away from a route, letting you check whether it is actually safe to leave, such as prompting the user to confirm if they have unsaved changes in a form that would otherwise be lost.
export const unsavedChangesGuard: CanDeactivateFn<EditFormComponent> = (component) => {
  if (component.hasUnsavedChanges()) {
    return confirm('You have unsaved changes, leave anyway?');
  }
  return true;
};

{ path: 'edit', component: EditFormComponent, canDeactivate: [unsavedChangesGuard] }
Real-world example A blog editor warns a writer with a confirmation dialog if they try to navigate away from an article with unsaved changes, using a canDeactivate guard to prevent accidentally losing their work.

Common follow-ups: What happens if the component being navigated away from does not implement the expected interface?;How would you build a more polished custom confirmation dialog instead of the plain browser confirm popup?

Forms;Angular Material & UI Component Libraries

What is a resolver in Angular routing, and what problem does it solve?

Intermediate
A resolver fetches data before a route actually activates, ensuring the component already has the data it needs the moment it appears on screen, rather than showing an empty or loading state and then fetching the data afterward inside the component itself.
export const userResolver: ResolveFn<User> = (route) => {
  const userService = inject(UserService);
  return userService.getUser(route.params['id']);
};

{ path: 'users/:id', component: UserDetailComponent, resolve: { user: userResolver } }
Real-world example A user profile page shows the user's details immediately upon arriving on the page, with no visible loading flicker at all, because a resolver already fetched that data before the route finished navigating.

Common follow-ups: How does a component actually access the data provided by a resolver?;What happens to navigation if the resolver's data fetch fails?

HTTP Client & Interceptors;Components & Templates

How would you combine multiple route guards together to enforce both authentication and a specific user role?

Advanced
You list several guard functions in the canActivate array for a route, and Angular runs them in order, only allowing navigation to proceed if every single guard returns true, letting you compose simple, focused guards together rather than writing one large guard handling everything at once.
export const adminGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  return authService.currentUser()?.role === 'admin';
};

{ path: 'admin', component: AdminPanelComponent, canActivate: [authGuard, adminGuard] }
Real-world example An admin panel requires both a general authGuard confirming the user is logged in at all, and a separate adminGuard confirming their specific role is admin, composing two small, focused guards together on the same route.

Common follow-ups: What happens if the guards need to run in a specific order to work correctly?;How would you share common logic between several related guards without duplicating code?

Design Patterns in Angular;Services & Dependency Injection

What is the difference between using a resolver and simply fetching data inside a component's ngOnInit method?

Beginner
Fetching data inside ngOnInit means the component renders first, often showing a brief loading state, before the data actually arrives. A resolver instead delays the route's navigation until the data has already been fetched, so the component appears fully populated with data from the very first moment it renders.
// ngOnInit approach, briefly shows a loading state
ngOnInit() {
  this.userService.getUser(this.id).subscribe((user) => this.user = user);
}

// Resolver approach, data is already available when the component renders
this.route.data.subscribe((data) => this.user = data['user']);
Real-world example A product detail page chooses to use a resolver specifically because showing a flash of empty content before the product details load in would feel jarring and unprofessional to shoppers browsing quickly.

Common follow-ups: Are there downsides to using a resolver, such as delaying the entire navigation while data loads?;When might showing a quick loading state inside the component actually be the better user experience?

Lifecycle Hooks;RxJS & Observables