I work on an Angular 17 application. I want to con...
创建于:2025年3月30日
创建于:2025年3月30日
I work on an Angular 17 application. I want to configure component input binding so I can use @Input decorator to automatically bind route parameters to inputs. How do I do that?
As of Angular v16.2+, the Router supports a new inputs property on route definitions that lets you wire up route parameters (and resolved data) directly to @Input() properties on your component—no extra subscription code needed. In other words, you can simply declare an @Input() in your component and have the router populate it automatically from the route parameters.
inputs mapping in your route configuration.@Input() properties in your component.Here’s a simple example:
tsimport { Routes } from '@angular/router'; import { UserDetailComponent } from './user-detail.component'; export const routes: Routes = [ { path: 'user/:userId', component: UserDetailComponent, inputs: { // Map the route parameter named 'userId' to the // 'userId' @Input() property in the component. userId: 'userId' } } ];
tsimport { Component, Input } from '@angular/core'; @Component({ selector: 'app-user-detail', template: `<p>User ID: {{ userId }}</p>` }) export class UserDetailComponent { @Input() userId!: string; // Will be set automatically from the route }
Now, whenever you navigate to a URL like /user/123, Angular’s Router will extract the userId parameter (123) and set it on the UserDetailComponent.userId input property.
The key in the inputs object must match the name of the route parameter (or a piece of resolved data).
The value in the inputs object must match the name of the @Input() property in the component.
This binding works similarly for route data or resolved data if you prefer. For example:
ts{ path: 'foo/:bar', component: FooComponent, resolve: { something: MyResolver }, inputs: { bar: 'bar', // route param something: 'details' // resolved data } }
tsexport class FooComponent { @Input() bar!: string; @Input() details!: any; }
inputs in the routing configuration.ActivatedRoute, subscribe to paramMap or data, and manually set the component fields. The router does it for you.ActivatedRoute as before. But for a simple “one-time read,” inputs is more convenient.That’s it! By adding the inputs mapping in your route definition and matching it to your @Input() properties, the Angular Router will take care of passing in route parameters (and even resolved data) automatically.
My app is on Angular 17.3.10 but the Route data type doesn't have the inputs property. What do I do?
inputs Property May Be MissingThe new inputs property on route definitions was introduced in Angular 16.2. If your project claims to be on Angular 17.3.10 but the Route interface doesn’t include inputs, one of two things is likely happening:
@angular/core or Angular CLI might be on some “17.x” version, but @angular/router is still on a version before 16.2 (so it doesn’t provide inputs in its type definitions or implementation).inputs feature, or the type definitions are incomplete.In short, the router code in your node_modules does not have the new inputs property yet. It doesn’t matter what version number your package.json says—if the router source and type definitions aren’t updated, the feature won’t work.
@angular/router Is the Correct VersionFirst, verify (in your package.json and lock file) that @angular/router is at least 16.2.0 (or the appropriate 17.x release that includes this feature). For example, run:
bashnpm list @angular/router
You might see something like @angular/[email protected] or 16.0.5 even though your Angular CLI says “17.x.” If the router is outdated, update explicitly:
bashng update @angular/router --force
Or install a matching version directly:
bashnpm install @angular/router@latest
Afterward, check your package.json to ensure that @angular/router is on a version 16.2+ or the 17.x equivalent.
If you cannot update (e.g., pinned by environment constraints) but want to try out inputs anyway, you can manually extend the Route interface to allow the property in TypeScript. Note, however, the router runtime still needs to support this feature; simply adding a type won’t make older router code magically handle it.
Extended interface:
tsimport { Route } from '@angular/router'; export interface ExtendedRoute extends Route { inputs?: { [key: string]: string }; }
Then use ExtendedRoute[] in your route config:
tsexport const routes: ExtendedRoute[] = [ { path: 'user/:id', component: UserDetailComponent, inputs: { id: 'userId' } } ];
This at least stops TypeScript from complaining about inputs. But if the router library you have installed does not include the code that wires up inputs → @Input(), then it still won’t actually pass values to the component. You must update the router to 16.2+ (or 17.x that includes the feature) to get real functionality.
If upgrading your router or using a pre-release that supports inputs is not feasible, revert to the traditional approach:
ts// user-detail.component.ts import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-user-detail', template: `User ID: {{ userId }}` }) export class UserDetailComponent { userId!: string; constructor(private route: ActivatedRoute) { this.route.paramMap.subscribe(params => { this.userId = params.get('id') ?? ''; }); } }
Or inject the ActivatedRouteSnapshot in a resolver/guard. That’s the standard solution prior to 16.2.
@angular/router is truly at least 16.2+ (or an Angular 17 version that includes the inputs feature).inputs property actually works at runtime.Route interface to avoid TypeScript errors, but the router must still contain the necessary logic in order to do the actual data binding. Otherwise, use the traditional param subscription approach until you can upgrade.