$stateParams / $routeParams in modern Angular
With withComponentInputBinding, the router passes path params, query params and resolved data straight into component inputs. ActivatedRoute remains available when you need the raw values.
Before · AngularJS
app.controller('UserDetailCtrl', function ($stateParams, UserService) {
var vm = this;
vm.tab = $stateParams.tab || 'profile';
UserService.get($stateParams.id).then(function (user) {
vm.user = user;
});
});After · Angular// app.config.ts
provideRouter(routes, withComponentInputBinding())
// route: { path: 'users/:id', component: UserDetailComponent }
export class UserDetailComponent {
private users = inject(UserService);
id = input.required<string>(); // :id
tab = input('profile', { // ?tab=
transform: (v: string | undefined) => v ?? 'profile',
});
user = toSignal(
toObservable(this.id).pipe(switchMap(id => this.users.get(id))),
);
}What changes
- The input name must match the param name; the value arrives as a string, so convert numbers with a transform.
- A missing query param arrives as undefined and replaces the input's default value; use a transform to restore the default.
- The router reuses the component when only the params change, so react to the input instead of reading it once.
Migration tip. Old controllers read $stateParams once because ui-router rebuilt them on every transition. Check each one for that assumption; it is the usual reason a migrated detail screen shows stale data.
Related
- abstract states and nested views
- named ui-view (multiple views)
- $urlRouterProvider.otherwise / redirectTo
- $state.go
Planning a migration or a micro-frontend platform?
In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.
Message me on LinkedIn