以下是我所做的更改。
products
,需要前往product-details
,因此我们后退一步../
到达product-dashboard
,然后导航至product-details
代码
getProductDetailsById(product: any, name: string) {
this.productService.get(product.id).subscribe((data: any) => {
this.router.navigate(
[
'../product-details', // we need to navigate one step back and then inside product details!
data['id'],
],
{
relativeTo: this.activateRoute,
}
);
});
}
其次,我们只需要在父级上监听选项卡选择
product-dashboard
我们可以从product-details
中删除代码
我添加了路由器参数订阅,因为它是动态的,即使组件没有被破坏,它也会显示正确的值!
代码
this.subscription.add(
this.route.params.subscribe((params: Params) => {
this.getProduct(+params['id']); // we get id as string, so we convert to number
})
);
ngOnDestroy
上取消订阅,这将防止应用程序中出现内存泄漏!我希望这能解决您的问题!
产品html
<div class="container">
<div class="list row ms-3">
<div class="col-md-12">
@if(!hidden){
<p-table [value]="products" styleClass="p-datatable-striped">
<ng-template pTemplate="header">
<tr>
<th>Name</th>
<th>Image</th>
<th>Category</th>
<th>Price</th>
<th>Actions</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-product>
<tr>
<td>{{ product.title }}</td>
<td>
<img
[src]="product.image"
[alt]="product.title"
width="100"
class="shadow-4"
/>
</td>
<td>{{ product.category }}</td>
<td>{{ product.price | currency: 'USD' }}</td>
<td>
<a
class="btn btn-outline-primary"
(click)="getProductDetailsById(product, 'product-details')"
>View</a
>
</td>
<td>
<a class="btn btn-info" (click)="getProductById(product)">Edit</a>
</td>
<td>
<button class="btn btn-danger" (click)="deleteProduct(product)">
Delete
</button>
</td>
</tr>
</ng-template>
<ng-template pTemplate="summary">
<div class="flex align-items-center justify-content-between">
In total there are {{ products ? products.length : 0 }} products.
</div>
</ng-template>
</p-table>
}
</div>
</div>
</div>
产品TS
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { RouterModule, Router, ActivatedRoute } from '@angular/router';
import { TableModule } from 'primeng/table';
import { of, Subscription } from 'rxjs';
import { ProductService } from '../product.service';
@Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css'],
imports: [RouterModule, TableModule, CommonModule],
standalone: true,
})
export class ProductsComponent implements OnInit {
subscription: Subscription = new Subscription();
hidden = false;
get products() {
return this.productService.products;
}
constructor(
private router: Router,
private productService: ProductService,
private activateRoute: ActivatedRoute
) {}
ngOnInit() {}
getProductDetailsById(product: any, name: string) {
this.subscription.add(
this.productService.get(product.id).subscribe((data: any) => {
this.router.navigate(
[
'../product-details', // we need to navigate one step back and then inside product details!
data['id'],
],
{
relativeTo: this.activateRoute,
}
);
})
);
}
getProductById(e: any) {}
deleteProduct(e: any) {}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
产品详情html
<div class="container">
<div class="row ms-3">
<div class="card" style="width: 18rem;">
<img
src="{{ currentProduct.image }}"
class="card-img-top"
alt="{{ currentProduct.title }}"
/>
<div class="card-body">
<h5 class="card-title">{{ currentProduct.title }}</h5>
<h3 class="card-title">{{ currentProduct.price | currency: 'USD' }}</h3>
<p class="card-text">{{ currentProduct.description }}</p>
</div>
</div>
</div>
</div>
产品详情
import { CommonModule } from '@angular/common';
import { Component, Inject, Input, OnInit } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import {
ActivatedRoute,
RouterLink,
NavigationEnd,
Router,
Params,
} from '@angular/router';
import { filter, Subscription } from 'rxjs';
import { ProductService } from '../product.service';
@Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.css'],
imports: [FormsModule, CommonModule, ReactiveFormsModule, RouterLink],
standalone: true,
})
export class ProductDetailsComponent {
subscription: Subscription = new Subscription();
@Input() currentProduct: any = {
title: '',
image: '',
category: '',
price: '',
};
nav: any;
message = '';
constructor(
private router: Router,
private route: ActivatedRoute,
private productService: ProductService
) {}
ngOnInit(): void {
this.message = '';
this.subscription.add(
this.route.params.subscribe((params: Params) => {
this.getProduct(+params['id']); // we get id as string, so we convert to number
})
);
}
getProduct(id: number): void {
this.subscription.add(
this.productService.get(id).subscribe({
next: (data: any) => {
this.currentProduct = data;
this.currentProduct.id = data['id'];
this.currentProduct.title = data['title'];
this.currentProduct.category = data['category'];
this.currentProduct.image = data['image'];
this.currentProduct.price = data['price'];
this.currentProduct.description = data['description'];
},
error: (e: any) => console.error(e),
})
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
产品仪表板 html
<nav #nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<button class="nav-link" id="nav-categories-tab" data-bs-toggle="tab" data-bs-target="#nav-categories" type="button" role="tab" aria-controls="nav-categories" aria-selected="true" (click)="showCategories()" [ngClass]="{ 'active':activeTab==='categories'}">Categories</button>
<button class="nav-link" id="nav-product-lists-tab" data-bs-toggle="tab" data-bs-target="#nav-product-lists" type="button" role="tab" aria-controls="nav-product-lists" aria-selected="false" (click)="showProducts()" [ngClass]="{ 'active':activeTab==='products'}">Products</button>
<button class="nav-link" id="nav-product-details-tab" data-bs-toggle="tab" data-bs-target="#nav-product-details" type="button" role="tab" aria-controls="nav-product-details" aria-selected="false" (click)="showProductDetails()" [ngClass]="{ 'active':activeTab==='product-details'}">Product Details</button>
</div>
<router-outlet/>
</nav>
产品仪表板 ts
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import {
ActivatedRoute,
provideRouter,
Router,
RouterModule,
NavigationEnd,
Routes,
} from '@angular/router';
import { filter } from 'rxjs/operators';
import { ProductService } from '../product.service';
@Component({
selector: 'app-products-dashboard',
templateUrl: './products-dashboard.component.html',
styleUrls: ['./products-dashboard.component.css'],
imports: [CommonModule, RouterModule],
providers: [ProductService],
standalone: true,
})
export class ProductsDashboardComponent {
activeTab = 'categories';
constructor(private router: Router, private route: ActivatedRoute) {
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(() => {
this.activeTab =
this.route?.snapshot?.firstChild?.routeConfig?.path?.split('/')[0] ||
'';
});
}
showCategories() {
this.router.navigate(['categories'], { relativeTo: this.route });
}
showProducts() {
this.router.navigate(['products'], { relativeTo: this.route });
}
showProductDetails() {
this.router.navigate(['product-details'], { relativeTo: this.route });
}
}