如何将Angular GET请求响应数据拆分加载到不同列表及变量中?
解决Angular对接Django REST API的数据拆分与渲染问题
问题核心
你的问题出在模型定义错误和服务返回类型不匹配,导致组件无法正确解析API返回的分页数据结构。
1. 修正ProductList模型定义
Django REST Framework的分页接口返回单个对象,包含分页元数据和data产品数组。你当前的data类型定义不符合TS语法,需单独定义Product接口并修正结构:
// products.models.ts export interface Product { id: number; name: string; picture: string; price: number; discount: number | null; saved_amount: number; discount_percent: number | null; slug: string; is_available: boolean; ratings_average: number; ratings_count: number; date: string; uuid: string; extra_data: any; category: Category; } export interface Category { // 根据API返回补充Category字段,示例: id: number; name: string; } export interface ProductList { total_pages: number; current_page: number; has_next: boolean; has_prev: boolean; page_items_count: number; items_per_page: number; data: Product[]; // 改为Product对象数组 } export interface ProductDetail {} // 后续补充详情结构
2. 修正ProductsService的返回类型
API返回的是单个分页对象而非数组,服务中所有返回ProductList[]的方法需改为ProductList:
// products.service.ts import { Injectable } from '@angular/core'; import { Observable, catchError, of } from 'rxjs'; import { ProductList, ProductDetail } from '../../models/products.models'; import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ProductsService { baseUrl = "http://127.0.0.1:8000/api"; headers = new HttpHeaders({ 'Content-Type': 'application/json', }); constructor(private http: HttpClient) { } private handleError(error: Error, errorValue: any) { return of(errorValue); } getProductList(): Observable<ProductList> { const productUrl = `${this.baseUrl}/products/` return this.http.get<ProductList>(productUrl, { headers: this.headers }).pipe( catchError((error) => this.handleError(error, { data: [], total_pages: 0 })) ); } getUnavailableProductList(): Observable<ProductList> { const productUrl = `${this.baseUrl}/products/unvailable/` return this.http.get<ProductList>(productUrl, { headers: this.headers }).pipe( catchError((error) => this.handleError(error, { data: [], total_pages: 0 })) ); } searchProducts(query: string|null): Observable<ProductList> { const params = query ? new HttpParams().set('q', query): {} const searchUrl = `${this.baseUrl}/products/search/` return this.http.get<ProductList>(searchUrl, { params: params, headers: this.headers }).pipe( catchError((error) => this.handleError(error, { data: [], total_pages: 0 })) ); } getProductDetail(product_id: number): Observable<ProductDetail|undefined> { const productDetailUrl = `${this.baseUrl}/products/${product_id}/` return this.http.get<ProductDetail>(productDetailUrl, { headers: this.headers }).pipe( catchError((error) => this.handleError(error, undefined)) ); } }
3. 在HomeComponent中正确拆分数据
组件中改为接收单个ProductList对象,提取产品列表和分页参数:
// homepage.component.ts import { Component, OnInit } from '@angular/core'; import { ProductList, Product } from '../../models/products.models'; import { ProductsService } from 'src/app/services/products/products.service'; @Component({ selector: 'app-homepage', templateUrl: './homepage.component.html', styleUrls: ['./homepage.component.css'] }) export class HomepageComponent implements OnInit { public products: Product[] = []; public total_pages: number = 0; public current_page: number = 0; public has_next: boolean = false; public has_prev: boolean = false; public page_items_count: number = 0; public items_per_page: number = 0; constructor (private productService: ProductsService) {} ngOnInit() { this.productService.getProductList().subscribe((res) => { this.products = res.data; this.total_pages = res.total_pages; this.current_page = res.current_page; this.has_next = res.has_next; this.has_prev = res.has_prev; this.page_items_count = res.page_items_count; this.items_per_page = res.items_per_page; }); } }
4. HTML模板中渲染数据
直接使用products数组遍历产品,分页参数直接绑定变量:
<!-- homepage.component.html --> <!-- 产品列表 --> <div *ngFor="let product of products" class="product-card"> <h3>{{ product.name }}</h3> <img [src]="product.picture" alt="{{ product.name }}"> <p>原价: {{ product.price }} 元</p> <p *ngIf="product.discount">折扣价: {{ product.price - product.saved_amount }} 元</p> <!-- 其他产品字段 --> </div> <!-- 分页控件 --> <div class="pagination-bar"> <button [disabled]="!has_prev">上一页</button> <span>第 {{ current_page }} 页 / 共 {{ total_pages }} 页</span> <button [disabled]="!has_next">下一页</button> <span>当前显示 {{ page_items_count }} 条 / 每页 {{ items_per_page }} 条</span> </div>
内容的提问来源于stack exchange,提问作者Stefan-ci
相关产品推荐
相关产品推荐

