liveBook · Manning

Route resolver

As explained in Pro Angular 16

A route resolver is an Angular routing mechanism that performs prerequisite work, such as loading data, before navigation completes.

A route resolver performs prerequisite work before Angular activates a route. Use one when navigating immediately would show an incomplete page while data loads. Unlike an activation guard, which can prevent navigation, a resolver delays activation until its work produces a result. section 26.2.1 section 26.2.2

Wait for product data

A five-second delay in a REST data source makes the problem visible: the application initially shows an incomplete layout. A model resolver instead returns a Promise that resolves when the model’s Products signal contains products. Angular waits for that Promise before activating the route. This particular condition assumes that at least one product will arrive; an empty product list would not satisfy it. section 26.2.1

Listing 26.2. The contents of the model.resolver.ts file in the src/app/model folder
import { Injectable, effect } from "@angular/core";
import { ActivatedRouteSnapshot, RouterStateSnapshot } 
    from "@angular/router";
import { Model } from "./repository.model"
import { Product } from "./product.model";
 
@Injectable()
export class ModelResolver {
    private promise: Promise<Product[]>;
 
    constructor(private model: Model) { 
        this.promise = new Promise((resolve) => {
            effect(() => {
                if (this.model.Products().length > 0) {
                    resolve(this.model.Products());
                }
            })
        });
    }
 
    resolve(route: ActivatedRouteSnapshot,
            state: RouterStateSnapshot) {
        return this.promise;
    }
}

The resolver injects the model, watches its Products signal with effect, and returns the resulting Promise from resolve. section 26.2.1

A resolver function—or a class’s resolve method—receives an ActivatedRouteSnapshot for the destination and a RouterStateSnapshot whose url describes the current route. These arguments can tailor the work to a navigation; the product example does not use them. A returned Observable delays activation until it emits, a Promise until it resolves, and another result only until it is produced. section 26.2.1

Listing 26.4. Applying a resolver in the app.routing.ts file in the src/app folder
import { Routes, RouterModule, mapToResolve } from "@angular/router";
import { TableComponent } from "./core/table.component";
import { FormComponent } from "./core/form.component";
import { NotFoundComponent } from "./core/notFound.component";
import { ProductCountComponent } from "./core/productCount.component";
import { CategoryCountComponent } from "./core/categoryCount.component";
import { ModelResolver } from "./model/model.resolver";

const childRoutes: Routes = [
    {   path: "",
        children: [{ path: "products", component: ProductCountComponent },
                   { path: "categories", 
                        component: CategoryCountComponent },
                   { path: "", component: ProductCountComponent }],
        resolve: { model: mapToResolve(ModelResolver) }
    }
];

const routes: Routes = [
    { path: "form/:mode/:id", component: FormComponent },     
    { path: "form/:mode", component: FormComponent },     
    { path: "does", redirectTo: "/form/create", pathMatch: "prefix" },
    { path: "table", component: TableComponent, children: childRoutes },
    { path: "table/:category", component: TableComponent, 
        children: childRoutes },
    { path: "", redirectTo: "/table", pathMatch: "full" },
    { path: "**", component: NotFoundComponent }]

export const routing = RouterModule.forRoot(routes, {
    bindToComponentInputs: true
});

After registering the class as a provider, attach it to a route with resolve: { model: mapToResolve(ModelResolver) }. The example places it on a parent route with product and category child routes. section 26.2.1

Waiting avoids displaying the destination’s incomplete content, but it can leave the user wondering why navigation has paused. Display a loading message or other placeholder until the resolver’s condition is satisfied. section 26.2.1 section 26.3

How Pro Angular 16 covers it

How deep it goes
Works through a resolver class, provider registration, route configuration, snapshot arguments, and return types; does not detail failure handling.
Examples
Uses a delayed REST product request, a model resolver waiting for products, route configuration, and a loading message.
What it assumes
Assumes Angular route configuration and services; briefly explains snapshot arguments and asynchronous resolver results.
What you can do after
Build it from scratch as an injectable Angular resolver and attach it to routes to defer activation until data arrives.
How it connects
Connects Angular routing to dependency injection, signals, Promises, Observables, loading placeholders, and route guards.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Pro Angular 16. The section links point to the parts of the book it draws on.