|
| 1 | +# Other common Routing Tasks |
| 2 | + |
| 3 | +This guide covers some other common tasks associated with using Angular router in your application. |
| 4 | + |
| 5 | +## Getting route information |
| 6 | + |
| 7 | +Often, as a user navigates your application, you want to pass information from one component to another. |
| 8 | +For example, consider an application that displays a shopping list of grocery items. |
| 9 | +Each item in the list has a unique `id`. |
| 10 | +To edit an item, users click an Edit button, which opens an `EditGroceryItem` component. |
| 11 | +You want that component to retrieve the `id` for the grocery item so it can display the right information to the user. |
| 12 | + |
| 13 | +Use a route to pass this type of information to your application components. |
| 14 | +To do so, you use the [`withComponentInputBinding`](api/router/withComponentInputBinding) feature with `provideRouter` or the `bindToComponentInputs` option of `RouterModule.forRoot`. |
| 15 | + |
| 16 | +To get information from a route: |
| 17 | + |
| 18 | +<docs-workflow> |
| 19 | + |
| 20 | +<docs-step title="Add `withComponentInputBinding`"> |
| 21 | + |
| 22 | +Add the `withComponentInputBinding` feature to the `provideRouter` method. |
| 23 | + |
| 24 | +```ts |
| 25 | +providers: [ |
| 26 | + provideRouter(appRoutes, withComponentInputBinding()), |
| 27 | +] |
| 28 | +``` |
| 29 | + |
| 30 | +</docs-step> |
| 31 | + |
| 32 | +<docs-step title="Add an `input` to the component"> |
| 33 | + |
| 34 | +Update the component to have an `input()` property matching the name of the parameter. |
| 35 | + |
| 36 | +```ts |
| 37 | +id = input.required<string>() |
| 38 | +hero = computed(() => this.service.getHero(id)); |
| 39 | +``` |
| 40 | + |
| 41 | +</docs-step> |
| 42 | +<docs-step title="Optional: Use a default value"> |
| 43 | +The router assigns values to all inputs based on the current route when `withComponentInputBinding` is enabled. |
| 44 | +The router assigns `undefined` if no route data matches the input key, such as when an optional query parameter is missing. |
| 45 | +You should include `undefined` in the `input`'s type when there's a possibility that an input might not be matched by the route. |
| 46 | + |
| 47 | +Provide a default value by either using the `transform` option on the input or managing a local state with a `linkedSignal`. |
| 48 | + |
| 49 | +```ts |
| 50 | +id = input.required({ |
| 51 | + transform: (maybeUndefined: string | undefined) => maybeUndefined ?? '0', |
| 52 | +}); |
| 53 | +// or |
| 54 | +id = input<string|undefined>(); |
| 55 | +internalId = linkedSignal(() => this.id() ?? getDefaultId()); |
| 56 | +``` |
| 57 | + |
| 58 | +</docs-step> |
| 59 | +</docs-workflow> |
| 60 | + |
| 61 | +NOTE: You can bind all route data with key, value pairs to component inputs: static or resolved route data, path parameters, matrix parameters, and query parameters. |
| 62 | +If you want to use the parent components route info you will need to set the router `paramsInheritanceStrategy` option: |
| 63 | +`withRouterConfig({paramsInheritanceStrategy: 'always'})` |
| 64 | + |
| 65 | +## Displaying a 404 page |
| 66 | + |
| 67 | +To display a 404 page, set up a [wildcard route](guide/routing/common-router-tasks#setting-up-wildcard-routes) with the `component` property set to the component you'd like to use for your 404 page as follows: |
| 68 | + |
| 69 | +```ts |
| 70 | +const routes: Routes = [ |
| 71 | + { path: 'first-component', component: FirstComponent }, |
| 72 | + { path: 'second-component', component: SecondComponent }, |
| 73 | + { path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page |
| 74 | +]; |
| 75 | +``` |
| 76 | + |
| 77 | +The last route with the `path` of `**` is a wildcard route. |
| 78 | +The router selects this route if the requested URL doesn't match any of the paths earlier in the list and sends the user to the `PageNotFoundComponent`. |
| 79 | + |
| 80 | +## Link parameters array |
| 81 | + |
| 82 | +A link parameters array holds the following ingredients for router navigation: |
| 83 | + |
| 84 | +- The path of the route to the destination component |
| 85 | +- Required and optional route parameters that go into the route URL |
| 86 | + |
| 87 | +Bind the `RouterLink` directive to such an array like this: |
| 88 | + |
| 89 | +```angular-html |
| 90 | +<a [routerLink]="['/heroes']">Heroes</a> |
| 91 | +``` |
| 92 | + |
| 93 | +The following is a two-element array when specifying a route parameter: |
| 94 | + |
| 95 | +```angular-html |
| 96 | +<a [routerLink]="['/hero', hero.id]"> |
| 97 | + <span class="badge">{{ hero.id }}</span>{{ hero.name }} |
| 98 | +</a> |
| 99 | +``` |
| 100 | + |
| 101 | +Provide optional route parameters in an object, as in `{ foo: 'foo' }`: |
| 102 | + |
| 103 | +```angular-html |
| 104 | +<a [routerLink]="['/crisis-center', { foo: 'foo' }]">Crisis Center</a> |
| 105 | +``` |
| 106 | + |
| 107 | +These three examples cover the needs of an application with one level of routing. |
| 108 | +However, with a child router, such as in the crisis center, you create new link array possibilities. |
| 109 | + |
| 110 | +The following minimal `RouterLink` example builds upon a specified default child route for the crisis center. |
| 111 | + |
| 112 | +```angular-html |
| 113 | +<a [routerLink]="['/crisis-center']">Crisis Center</a> |
| 114 | +``` |
| 115 | + |
| 116 | +Review the following: |
| 117 | + |
| 118 | +- The first item in the array identifies the parent route \(`/crisis-center`\) |
| 119 | +- There are no parameters for this parent route |
| 120 | +- There is no default for the child route so you need to pick one |
| 121 | +- You're navigating to the `CrisisListComponent`, whose route path is `/`, but you don't need to explicitly add the slash |
| 122 | + |
| 123 | +Consider the following router link that navigates from the root of the application down to the Dragon Crisis: |
| 124 | + |
| 125 | +```angular-html |
| 126 | +<a [routerLink]="['/crisis-center', 1]">Dragon Crisis</a> |
| 127 | +``` |
| 128 | + |
| 129 | +- The first item in the array identifies the parent route \(`/crisis-center`\) |
| 130 | +- There are no parameters for this parent route |
| 131 | +- The second item identifies the child route details about a particular crisis \(`/:id`\) |
| 132 | +- The details child route requires an `id` route parameter |
| 133 | +- You added the `id` of the Dragon Crisis as the second item in the array \(`1`\) |
| 134 | +- The resulting path is `/crisis-center/1` |
| 135 | + |
| 136 | +You could also redefine the `AppComponent` template with Crisis Center routes exclusively: |
| 137 | + |
| 138 | +```angular-ts |
| 139 | +@Component({ |
| 140 | + template: ` |
| 141 | + <h1 class="title">Angular Router</h1> |
| 142 | + <nav> |
| 143 | + <a [routerLink]="['/crisis-center']">Crisis Center</a> |
| 144 | + <a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a> |
| 145 | + <a [routerLink]="['/crisis-center/2']">Shark Crisis</a> |
| 146 | + </nav> |
| 147 | + <router-outlet /> |
| 148 | + ` |
| 149 | +}) |
| 150 | +export class AppComponent {} |
| 151 | +``` |
| 152 | + |
| 153 | +In summary, you can write applications with one, two or more levels of routing. |
| 154 | +The link parameters array affords the flexibility to represent any routing depth and any legal sequence of route paths, \(required\) router parameters, and \(optional\) route parameter objects. |
| 155 | + |
| 156 | +## `LocationStrategy` and browser URL styles |
| 157 | + |
| 158 | +When the router navigates to a new component view, it updates the browser's location and history with a URL for that view. |
| 159 | + |
| 160 | +Modern HTML5 browsers support [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state'), a technique that changes a browser's location and history without triggering a server page request. |
| 161 | +The router can compose a "natural" URL that is indistinguishable from one that would otherwise require a page load. |
| 162 | + |
| 163 | +Here's the Crisis Center URL in this "HTML5 pushState" style: |
| 164 | + |
| 165 | +```text |
| 166 | +localhost:3002/crisis-center |
| 167 | +``` |
| 168 | + |
| 169 | +Older browsers send page requests to the server when the location URL changes unless the change occurs after a "#" \(called the "hash"\). |
| 170 | +Routers can take advantage of this exception by composing in-application route URLs with hashes. |
| 171 | +Here's a "hash URL" that routes to the Crisis Center. |
| 172 | + |
| 173 | +```text |
| 174 | +localhost:3002/src/#/crisis-center |
| 175 | +``` |
| 176 | + |
| 177 | +The router supports both styles with two `LocationStrategy` providers: |
| 178 | + |
| 179 | +| Providers | Details | |
| 180 | +| :--------------------- | :----------------------------------- | |
| 181 | +| `PathLocationStrategy` | The default "HTML5 pushState" style. | |
| 182 | +| `HashLocationStrategy` | The "hash URL" style. | |
| 183 | + |
| 184 | +The `RouterModule.forRoot()` function sets the `LocationStrategy` to the `PathLocationStrategy`, which makes it the default strategy. |
| 185 | +You also have the option of switching to the `HashLocationStrategy` with an override during the bootstrapping process. |
| 186 | + |
| 187 | +HELPFUL: For more information on providers and the bootstrap process, see [Dependency Injection](guide/di/dependency-injection-providers). |
0 commit comments