为什么这个变量 return 未定义而不是我的 Angular 13 应用程序中的对象?

Why does this variable return undefined instead of an object in my Angular 13 app?

我正在开发一个电子商务应用程序,它的前端是在 Angular 13.

中制作的

我使用一项服务来处理来自 API 的产品。我 运行 在显示 产品详细信息 时遇到问题。

参见 Stackblitz 演示 HERE

app\services\product.service.ts 我有:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Product, ProductResponse } from '../models/product';

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  products: Product[] = [];

  apiURL: string = 'https://dummyjson.com';

  constructor(private http: HttpClient) {}
  
  // Product List       
  public getProducts(): Observable<ProductResponse>{
    return this.http.get<ProductResponse>(`${this.apiURL}/products`);
  }

  // Product Details (single product)
  public getProductDetails(id: Number): Observable<ProductResponse>{
    return this.http.get<ProductResponse>(`${this.apiURL}/products/${id}`);
  }
}

app\app.module.ts中:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { Routes, RouterModule } from '@angular/router';
import { NavbarComponent } from './components/navbar/navbar.component';
import { FooterComponent } from './components/footer/footer.component';
import { SidebarComponent } from './components/sidebar/sidebar.component';
import { HomeComponent } from './components/home/home.component';
import { ProductItemComponent } from './components/product-item/product-item.component';
import { ProductsListComponent } from './components/products-list/products-list.component';
import { ProductsDetailsComponent } from './components/products-details/products-details.component';

const routes: Routes = [
  { path: '', component:  HomeComponent},
  { path: 'products', component:  ProductsListComponent},
  { path: 'products/show/:id', component:  ProductsDetailsComponent},
];

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent,
    FooterComponent,
    SidebarComponent,
    ProductsListComponent,
    ProductItemComponent ,
    ProductsDetailsComponent
  ],
  imports: [
    CommonModule,
    BrowserModule,
    HttpClientModule,
    RouterModule.forRoot(routes),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app\models\product.ts中:

export class Product {
    id?: number;
    title?: string;
    description?: string;
    price?: number;
    discountPercentage?: number;
    rating?: number;
    stock?: number;
    brand?: string;
    category?: string;
    thumbnail?: string;
}

export interface ProductResponse {
    products: Product[];
    total: number;
    skip: number;
    limit: number;
}

app\components\products-details\products-details.component.ts 我有:

import { Component, OnInit, InputDecorator, Input } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Product, ProductResponse } from '../../models/product';
import { ProductService } from '../../services/product.service';

@Component({
  selector: 'app-products-details',
  templateUrl: './products-details.component.html',
  styleUrls: ['./products-details.component.css']
})
export class ProductsDetailsComponent implements OnInit {

  @Input() product!: Product;
  productResponse: any;

  constructor(private ProductService: ProductService, private Router: Router, private ActivatedRoute:ActivatedRoute) { }

  ngOnInit(): void {
    const id = Number(this.ActivatedRoute.snapshot.paramMap.get('id'));
    this.ProductService.getProductDetails(id).subscribe((response) => (this.productResponse = response));

  }
}

app\components\products-details\products-details.component.html我有:

<h1>{{ product.title }}</h1>

问题

当我访问产品详细信息路由(例如,http://localhost:4200/products/show/1)时,页面显示一个空的 <h1> 标签,Chrome 控制台显示 Cannot read properties of undefined (reading 'title')

我的错误在哪里?

@Input() 属性 仅适用于外部赋值。

以下可能会满足您的要求:

product: Product | undefined;
this.ProductService.getProductDetails(id).subscribe((response) => (this.product = response));
<h1>{{ product?.title }}</h1>

此外,我认为处理原始响应应该发生在服务而不是组件中,但这可能是个人喜好问题。

https://dummyjson.com/products 端点不同,https://dummyjson.com/products/{id} returns 是一个普通的 Product 对象,因此:

// product.service.ts
public getProductDetails(id: Number): Observable<Product>{
  return this.http.get<Product>(`${this.apiURL}/products/${id}`);
}

// products-details.component.ts
// the @Input decorator is wrong — the data is not passed to the component from outside
// but instead fetched inside of the component
@Input() product!: Product;
// productResponse: any — this field is unused and should be removed

ngOnInit(): void {
  ...
  this.ProductService.getProductDetails(id).subscribe((product) => (this.product = product));
}