使选项卡在父组件的角度中处于活动状态

问题描述 投票:0回答:1
angular twitter-bootstrap bootstrap-5 primeng bootstrap-tabs
1个回答
0
投票

以下是我所做的更改。

  • 首先进行导航,我们位于
    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 });
  }
}

堆栈闪电战

© www.soinside.com 2019 - 2024. All rights reserved.