I have page with a list of products, and I want to pass product id to a product/:id router (I don't want to parse it from router url). What options do I have? Can I have something like Input()
to a router component?
问题:
回答1:
Let me get this right first!
You have a list of items and when you click on one, you need to redirect to a general route that displays the details in reference to the item id? You are looking for a way to pass the item id to the child component without passing it as a route parameter?
This is basically sharing data among components. There are 4 ways of doing that.
Parent to Child: Sharing Data via Input
This is probably the most common and straightforward method of sharing data. It works by using the @Input()
decorator to allow data to be passed via the template.
Child to Parent: Sharing Data via ViewChild
ViewChild
allows one component to be injected into another, giving the parent access to its attributes and functions. One caveat, however, is that the child won’t be available until after the view has been initialized. This means we need to implement the AfterViewInit
lifecycle hook to receive the data from the child.
Child to Parent: Sharing Data via Output()
and EventEmitter
This approach is ideal when you want to share data changes that occur on things like button clicks, form entries, and other user events.
In the parent, you can create a function to receive the message and set it equal to the message variable.
In the child, declare a messageEvent
variable with the Output decorator and set it equal to a new event emitter. Then create a function named sendMessage
that calls emit on this event with the message you want to send. Lastly, create a button to trigger this function.
The parent can now subscribe to this messageEvent
that’s outputted by the child component, then run the receive message function whenever this event occurs.
Unrelated Components: Sharing Data with a Service (Recommended)
When passing data between components that lack a direct connection, such as siblings, grandchildren, etc, you should you a shared service. When you have data that should always be in sync, I find the RxJS BehaviorSubject
very useful in this situation.
following is an example on the last approach!
shared-service.ts
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable() export class DataService { private messageSource = new BehaviorSubject('default message'); currentMessage = this.messageSource.asObservable(); constructor() { } changeMessage(message: string) { this.messageSource.next(message) } }
parent.component.ts
import { Component, OnInit } from '@angular/core'; import { DataService } from "../data.service"; @Component({ selector: 'app-parent', template: ` {{message}} `, styleUrls: ['./sibling.component.css'] }) export class ParentComponent implements OnInit { message:string; constructor(private data: DataService) { } ngOnInit() { //subscribing to the updated data set this.data.currentMessage.subscribe(message => this.message = message) } }
sibling.component.ts
import { Component, OnInit } from '@angular/core'; import { DataService } from "../data.service"; @Component({ selector: 'app-sibling', template: ` {{message}} <button (click)="newMessage()">New Message</button> `, styleUrls: ['./sibling.component.css'] }) export class SiblingComponent implements OnInit { message:string; constructor(private data: DataService) { } ngOnInit() { this.data.currentMessage.subscribe(message => this.message = message) } newMessage() { // triggering the shared service method this.data.changeMessage("Hello from Sibling") } }
I hope this approach works.
Good Luck!
回答2:
import { Router } from '@angular/router';
constructor(private router: Router) { }
Use as a path Variable
In app.routes.ts
{ path: 'product/:id' , component: ProductComponent}
How to use in html file
<a [routerLink]="['/product', product.id ]">Your link<a>
Here product.id is the value you wants to pass
How to use in in typescript file
this.router.navigate(['/product', this.product.id]);
Here this.product.id is the value you wants to pass
Use as a optional parameter
In app.routes.ts
{ path: 'product' , component: ProductComponent}
How to use in html file
<a [routerLink]="['/product', { id: product.id} ]">Your link<a>
Here product.id is the value you wants to pass
How to use in in typescript file
this.router.navigate(['/product',{ id : this.product.id} ]);
Here this.product.id is the value you wants to pass
Use as a Query parameter
In app.routes.ts
{ path: 'product' , component: ProductComponent}
How to use in html file
<a [routerLink]="['/product']" [queryParams]="{ id: product.id}">Your link<a>
Here product.id is the value you wants to pass
How to use in in typescript file
this.router.navigate(['/product'], { queryParams: { id : this.product.id}});
Here this.product.id is the value you wants to pass