products-list.component.ts (2370B)
1 import { Component, effect, inject, input, signal } from '@angular/core'; 2 import { CommonModule } from '@angular/common'; 3 import { ProductService } from './products.service'; 4 import { Router } from '@angular/router'; 5 import { PaginateComponent } from './paginate.component'; 6 import { ProductComponent } from './product.component'; 7 8 @Component({ 9 selector: 'div.products-list', 10 templateUrl: './products-list.component.html', 11 styleUrls: ['./products-list.component.scss'], 12 standalone: true, 13 imports: [CommonModule, PaginateComponent, ProductComponent], 14 }) 15 export class ProductsListComponent { 16 private productService = inject(ProductService); 17 private router = inject(Router); 18 19 // Input signals automatically bound from query parameters 20 readonly page = input<number, string | number>(1, { 21 transform: (value: string | number) => { 22 const num = typeof value === 'string' ? parseInt(value, 10) : value; 23 return isNaN(num) ? 1 : Math.max(1, num); 24 } 25 }); 26 27 readonly pageSize = input<number, string | number>(10, { 28 transform: (value: string | number) => { 29 const num = typeof value === 'string' ? parseInt(value, 10) : value; 30 return isNaN(num) || ![10, 20, 50, 100].includes(num) ? 10 : num; 31 } 32 }); 33 34 // State signals 35 readonly products = signal<ProductCard[]>([]); 36 readonly loading = signal<boolean>(false); 37 readonly error = signal<string | null>(null); 38 readonly totalPages = signal<number>(0); 39 readonly total = signal<number>(0); 40 41 constructor() { 42 // Effect to load products when page or pageSize changes 43 effect(() => { 44 const currentPage = this.page(); 45 const currentPageSize = this.pageSize(); 46 this.loadProducts(currentPage, currentPageSize); 47 }); 48 } 49 50 private loadProducts(page: number, pageSize: number): void { 51 this.loading.set(true); 52 this.error.set(null); 53 54 this.productService.getProducts(page, pageSize).subscribe({ 55 next: (response) => { 56 this.products.set(response.products); 57 this.totalPages.set(response.total_pages); 58 this.total.set(response.total); 59 this.loading.set(false); 60 }, 61 error: (err) => { 62 console.error('Failed to load products:', err); 63 this.error.set('Failed to load products. Please try again.'); 64 this.products.set([]); 65 this.loading.set(false); 66 }, 67 }); 68 } 69 }