Reputation: 16959
Hi I am trying to extract the id part of the URL using Angular2.
http://localhost:3000/item/187809
I have been playing around with ActiveRoute
within onInit
but without luck
this.route.queryParams.forEach((params: any) => {
console.log("QUERYPARAMS");
console.log(params);
});
Also tried subscribing to route change like this
this.routeSub = this.route.queryParams.subscribe(params => {
console.log(params);
console.log(+params['id']);
});
but params
is just an empty object.
I am defining the route as a lazy route like this
{
path: item',
children: [
{ path: ':id', loadChildren: './item/item.module#ItemModule'},
]
},
I think the problem is that I have a header component and a main component which holds the lazy loaded routed child. I am trying to load the id inside the header component.
Any idea what's missing?
Upvotes: 88
Views: 147821
Reputation: 468
Based on @Sos Sargsyan answer, I'm presenting the same solution with an @Input decorator:
app.config.ts
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes, withComponentInputBinding())]
};
app.route.ts
export const routes: Routes = [
{
path: 'data/:sensorName',
component: DataComponent,
title: 'Data'
}
]
data.component.ts
@Component({
selector: 'app-data',
standalone: true,
imports: [RouterOutlet, RouterLink, CommonModule],
templateUrl: './data.component.html',
styleUrl: './data.component.scss'
})
export class DataComponent implements OnInit, OnDestroy {
@Input()
set sensorName(name: string) {
this.youService.getData(
name
).subscribe();
}
}
As the previous author mentioned, the component must also have an input property with the same name as the parameter passed by the router. In the example above, the property name is sensorName, which matches the parameter from the router path: sensorName.
withComponentInputBinding()
Enables binding information from the Router state directly to the inputs of the component in Route configurations. https://angular.dev/api/router/withComponentInputBinding?tab=api
@Input
The input property is bound to a DOM property in the template. During change detection, Angular automatically updates the data property with the DOM property's value.
https://v17.angular.io/api/core/Input
Upvotes: 0
Reputation: 365
Actually there are multiple ways of extracting id from router into the component.
But I would like to mention that there is a new method in Angular.
Starting with Angular 17 you can use withComponentInputBinding
to bind route parameters directly to component's inputs. And in this case there is no need for manual subscription to route parameters. Here's how you can do it:
1.Enable the feature in app.config.ts file
const appRoutes: Routes = [];
bootstrapApplication(AppComponent,
{
providers: [
provideRouter(appRoutes, withComponentInputBinding())
]
}
);
2. Define your route in app.routes.ts file
import { Routes } from '@angular/router';
import { TasksComponent } from './tasks/tasks.component';
import { TaskDetailsComponent } from './tasks/task-details.component';
export const routes: Routes = [
{
path: 'tasks',
component: TasksComponent,
},
{
path: 'tasks/:taskId',
component: TaskDetailsComponent,
},
];
3. Extract taskId parameter in your TaskDetailsComponent
import { Component, input } from '@angular/core';
@Component({
selector: 'app-task-details',
standalone: true,
templateUrl: './task-details.component.html',
styleUrl: './task-details.component.css',
})
export class TaskDetailsComponent {
taskId = input.required<string>();
}
Important Note:
If the route parameter is named
taskId
then the component must also have an input namedtaskId
. If these names do not match, Angular will not be able to perform the binding, and the input will remain undefined.
Upvotes: 2
Reputation: 3312
Subscribing and Unsubscribing to Route Parameters
{path: 'item/:id', component: SomeItemComponent}
private routeSub: Subscription;
constructor(private route: ActivatedRoute) { }
params
observable by subscribing to it like so:ngOnInit() {
this.routeSub = this.route.params.subscribe(params => {
console.log(params) //log the entire params object
console.log(params['id']) //log the value of id
});
}
ngOnDestroy() {
this.routeSub.unsubscribe();
}
There is a big difference between route.params
and route.queryParams
.
route.params
, when subscribed to, returns an object with keys (that come from your route parameters, see step 1) and string values that are provided when navigating to the route. For example:
example.com/item/1
{
itemId: '1'
}
route.queryParams
, when subscribed to, returns an object with keys and string values that come from the query string (wiki) in the URL. For example:
example.com/welcome?var1=abc&var2=cde
{
var1: 'abc',
var2: 'cde'
}
route.queryParams
will be undefined
if a query string is not present in the URL. I believe OP, and some users in the comments have mistakenly used this instead of route.params
.
Upvotes: 147
Reputation: 873
I suspect the issue is that you're using queryParams
instead of just params
.
params: An Observable that contains the required and optional parameters specific to the route.
queryParams: An Observable that contains the query parameters available to all routes.
so try this:
this.route.params.subscribe(params => {
console.log(params);
console.log(+params['id']);
});
Upvotes: 12
Reputation: 37403
this.routeSub = this.route.params.subscribe(params => {
console.log(params);
console.log(+params['id']);
});
Upvotes: 3
Reputation: 4699
I know I'm a bit late with a reply, but just in case you were still having problem please take a look at the Angular documentation.
Look at the example from the link.
Start by importing ActivatedRoute:
import { ActivatedRoute } from '@angular/router';
Then inject it in the constructor
constructor(private route: ActivatedRoute) {}
And in OnInit()
ngOnInit(): void {
const id = this.route.snapshot.paramMap.get('id');
}
and like this you don't need to worry about any Observables directly.
Hope this helps you.
Upvotes: 69
Reputation: 116
I have faced the same problem while working with Angular 8, and solved it by:
import { ActivatedRoute } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute) {}
ngOnInit(){
const id = this.activatedRoute.snapshot.paramMap.get('id');
}
I found it from the official documentation of Angular.
Upvotes: 4
Reputation: 14872
You have multi options to get id
constructor(private route: ActivatedRoute) { }
1-With the help of params
const id= this.route.snapshot.params['id'];
or
const id = this.route.snapshot.params.id // any param name after "params"
2-With the help of paramMap
const id= this.route.snapshot.paramMap.get('id')
3-subscribe
to params
(do not forget to unsubscribe)
private subscription: Subscription
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
this.subscription = this.route.params.subscribe(params => {
const id = params['id']
})
}
//To prevent memory leak
ngOnDestroy(): void {
if (this.subscription)
this.subscription.unsubscribe()
}
{
path: "",
component: LayoutComponent,
children: [
{
path: "action/:id", component: ChildComponent
}
]
}
If you are in the LayoutComponent and you want to get params of ChildComponent you have to use the following way:
this.route.children.forEach(child => {
child.params.subscribe(params => {
const id = params['id']
})
}
Upvotes: 13