Advanced Angular

Preview — 3 of 10 questions

What does resource(), introduced in Angular 19, do?

javascript
import { resource, signal } from '@angular/core';

@Component({
  template: `
    @if (userResource.isLoading()) { <p>Loading…</p> }
    @else if (userResource.error()) { <p>Error!</p> }
    @else { <p>{{ userResource.value()?.name }}</p> }
  `
})
export class UserComponent {
  userId = signal(1);

  userResource = resource({
    request: () => ({ id: this.userId() }),
    loader: ({ request }) => fetch(`/api/users/${request.id}`).then(r => r.json()),
  });
}
Aresource() is an alias for computed() — it has no loading-state handling
Bresource() creates an async signal that automatically manages loading/error/value states. When the signals read in request() change, the loader re-runs automatically and the states update
Cresource() completely replaces HttpClient — it only works with fetch()
Dresource() requires Zone.js to work

How do you add an authentication header to every HTTP request?

javascript
// auth.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const auth = inject(AuthService);
  const token = auth.getToken();

  if (!token) return next(req);

  const authReq = req.clone({
    headers: req.headers.set('Authorization', `Bearer ${token}`),
  });

  return next(authReq);
};

// app.config.ts
providers: [
  provideHttpClient(withInterceptors([authInterceptor])),
]
Areq.headers.set() mutates the original request's headers in place
BwithInterceptors() runs the interceptors in reverse order of the list
Cinject() cannot be used in an interceptor — you must use the constructor
DThe code is correct. Angular HTTP requests are immutable — req.clone() creates a modified copy. HttpInterceptorFn is the modern (Angular 15+) class-free style

How do you protect a route with an Angular 15+ guard?

javascript
// auth.guard.ts
export const authGuard: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  if (auth.isLoggedIn()) return true;

  return router.createUrlTree(['/login'], {
    queryParams: { returnUrl: state.url }
  });
};

// Routes:
{
  path: 'dashboard',
  canActivate: [authGuard],
  component: DashboardComponent,
}
ACanActivateFn may only return true or false
Binject() in a functional guard creates a new service instance on every navigation
CCanActivateFn can return boolean, UrlTree (redirect), or an Observable/Promise of those types. Returning a UrlTree is the recommended way to redirect from a guard
DFunctional guards don't support asynchronous checks

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.