这是我的产品dashboard.html

   <nav #nav>
    <div class="nav nav-tabs" id="nav-tab" role="tablist">
      <button class="nav-link active" 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>
  </nav>

这是我的产品仪表板组件

    export class ProductsDashboardComponent {
    activeTab = 'categories';
    constructor(private router:Router, private route: ActivatedRoute){}
    showCategories(){
      this.router.navigate(['categories'],{relativeTo: this.route})
    }
    showProducts(){
      this.router.navigate(['products'],{relativeTo: this.route})
    }
    showProductDetails(){
      this.activeTab = 'product-details';
      this.router.navigate(['product-details'],{relativeTo: this.route})
    }
  }

现在,当我单击产品详细信息选项卡时,前一个选项卡(即产品选项卡)也显示为活动的,如下所示.那么,如何使Other Tabs类处于非活动状态.

enter image description here

Products.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>

产品组件

 getProductDetailsById(product: Products,name:string){
    this.productService.get(product.id)
      .subscribe( data => {
       this.currentProduct=data;
       this.currentIndex = data["id"],
       this.parent.activeTab = name;
       this.router.navigate(['products-dashboard/product-details/',this.currentIndex])
      })
}

enter image description here

现在,如果我点击查看按钮,它应该导航到产品-详细信息标签

Product-details.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 { Component, Inject, Input, OnInit, ViewChild } from '@angular/core';
import {ActivatedRoute, NavigationEnd, Router, RouterLink } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { Products } from '../models/products.model';
import {ProductService } from '../services/products.service';
import { ProductsDashboardComponent } from '../products-dashboard/products-dashboard.component';
import { filter } from 'rxjs';
@Component({
  selector: 'app-product-details',
  standalone: true,
  imports: [FormsModule, CommonModule,ReactiveFormsModule, RouterLink],
  providers:[ProductService],
  templateUrl: './product-details.component.html',
  styleUrl: './product-details.component.css'
})
export class ProductDetailsComponent implements OnInit{
  
   @Input() currentProduct: Products = {
     title: '',
     image: '',
     category:'',
     price: ''
   };
   nav:any;
   message = '';
   activeTab = 'categories';
   constructor(
    private router:Router, private route: ActivatedRoute,
     private productService: ProductService,
     @Inject(ProductsDashboardComponent) private parent: ProductsDashboardComponent) {}

   ngOnInit(): void {
       this.message = '';
       this.router.events.pipe(
        filter(event => event instanceof NavigationEnd)
      ).subscribe(() => {
        this.parent.activeTab = this.route?.snapshot?.firstChild?.routeConfig?.path || '';
      })
       this.getProduct(this.route.snapshot.params["id"]);
  }

   getProduct(id: string): void {
     this.productService.get(id)
       .subscribe({
         next: (data) => {
           this.currentProduct = data;
           console.log(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) => console.error(e)
       });
   }
}

现在,产品本身显示在相同的选项卡中

enter image description here

App.routes.ts

export const routes: Routes = [
    { path: '',   redirectTo: '/home', pathMatch: 'full' }, // redirect to `first-component`
    { path: 'home', component: HomeComponent}, 
    { path: 'hooks', component: HooksComponent}, 
    { path: 'dashboard', component: DashboardComponent}, 
    { path: 'products-dashboard', component: ProductsDashboardComponent,
      children:[
        {path: 'categories', component: CategoriesComponent},
        {path: 'products', component: ProductsComponent},
        {path: 'product-details', component: ProductDetailsComponent},
        {path: "product-details/:id", component: ProductDetailsComponent },
      ]
    },
    { path: '**', component: PagenotfoundComponent },  // Wildcard route for a 404 page
  ];

推荐答案

以下是我所做的更改.

  • First for navigation, we are at <编码>products and need to go to <编码>product-details so we go one step back <编码>../ to <编码>product-dashboard and then we navigate to <编码>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,
        }
      );
    });
  }
  • Second, we need to listen for the tab selection only on the parent <编码>product-dashboard we can remove the 编码 from <编码>product-details

  • 我已经添加了路由参数订阅,因为它将动态,即使组件没有被 destruct ,也会显示适当的值!

编码

<编码> this.subscription.add(
  this.route.params.subscribe((params: Params) => {
    this.getProduct(+params['id']); // we get id as string, so we convert to number
  })
);
  • Wherever we have a subscribe we need to add it to a subscription and unsubscribe on <编码>ngOnDestroy this will prevent memory leaks in your application!

我希望这能解决你的问题!

产品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>

产品展示

<编码>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>

产品详情%ts

<编码>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 });
  }
}

stackblitz

Angular相关问答推荐

将Angular Metal的芯片组件集成到我的表单中时出错

使用路由进行测试.为每次测试导航堆栈

Angular 升级到v16和Ant设计错误:';nzComponentParams';类型';ModalOptions';中不存在

[NullInjectorError]:R3InjectorError(Standalone[_AppComponent])[]:NullInjectorError:No provider for _HttpClient

如何让 ag-Grid 事件读取私有方法?

获取 Angular 中所有子集合 firestore 的列表

Angular *ngIf 表达式中这么多冒号的作用是什么?

使用 primeng Apollo 主题进行实时部署时多次加载 theme.css 和 preloading.css 文件

在 kubernetes 上创建 Ingress 服务以将 springboot [后端] 连接到前端 [angular]

没有调用订阅的原因是什么?

BehaviorSubject 在 Angular 中制作数据之间的时间表(或计时器)

如何禁用特定数据集图表js的默认标签

带有数据的 Angular 模板

as和let之间的异步管道区别

使用 Angular2 将文件上传到 REST API

导航到同一条route路由不刷新组件?

ConnectionBackend 没有提供程序

如何手动延迟加载模块?

如何在 Angular 2 中链接 HTTP 调用?

路由 getCurrentNavigation 始终返回 null