Tablas con filtros y debounce
Clase 22 de 24 • Curso de Maquetación con Angular CDK y Tailwind CSS
Contenido del curso
Clase 22 de 24 • Curso de Maquetación con Angular CDK y Tailwind CSS
Contenido del curso
Elcira Ibarra
Vladimir Raigosa
Victor Alfredo Matzar Say
Victor Alfredo Matzar Say
Vladimir Raigosa
Patrick Feeney
Gersom Hernandez
Max Andy Diaz Neyra
Max Andy Diaz Neyra
carlos andres Gudiño
Pablo García Rodríguez
Jhon Pabon
Mi solución al reto:
// data-source.ts find(query: string) { const newProducts = this.originalData.filter(item => item.title.toLowerCase().includes(query.toLowerCase()) || item.id == query || item.price === Number(query) ) this.data.next(newProducts); }
Encontré este articulo donde explican el manejo de sort y paginator:
Aparece con un error
Mi solución al reto :):
const newProducts = this.originalData.filter((element) => { return element.title.toLowerCase().includes(query.toLowerCase()) || element.id.toString().includes(query) || element.price.toString().includes(query); })
Usando este enfoque de extender el DataSource como se puede hacer un sort y un paginator a la tabla??
Muy simple y bueno. Me gusto
Me parece que el datasource esta tomando forma de Facade o esa es mi percepción
Mi solución adaptada a Angular 19 que maneja la reactividad con signal:
import { Component, computed, inject } from '@angular/core'; import { CdkTableModule } from '@angular/cdk/table'; import { rxResource, toSignal } from '@angular/core/rxjs-interop'; import { CommonModule } from '@angular/common'; import { NavbarComponent } from '../../components/navbar/navbar.component'; import { ProductService } from '../../services/product.service'; import { BtnComponent } from '../../components/btn/btn.component'; import { Product } from '../../models/product.model'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { debounceTime } from 'rxjs'; @Component({ selector: 'app-table', imports: [ NavbarComponent, CdkTableModule, CommonModule, BtnComponent, ReactiveFormsModule, ], templateUrl: './table.component.html', }) export class TableComponent { private productService = inject(ProductService); readonly products = rxResource({ loader: () => this.productService.getProducts(), defaultValue: [], }); // filteredProducts = signal<Product[]>([]); input = new FormControl('', { nonNullable: true }); readonly search = toSignal(this.input.valueChanges.pipe(debounceTime(300)), { initialValue: '', }); filteredProducts = computed(() => { const query = this.search(); const products = this.products.value(); return products.filter( (product) => product.title.toLowerCase().includes(query.toLowerCase()) || product.id.toString().includes(query) || product.price.toString().includes(query), ); }); readonly totalPrice = computed(() => { const products = this.products.value(); return products.reduce((acc, product) => acc + Number(product.price), 0); }); private updateData(id: Product['id'], changes: Partial<Product>) { this.products.update((products) => products.map((product) => product.id === id ? { ...product, ...changes } : product, ), ); } // ngOnInit() { // this.input.valueChanges.pipe(debounceTime(3000)).subscribe((value) => { // this.find(value); // }); // } update(product: Product) { this.updateData(product.id, { price: 20 }); } // find(query: string) { // const filteredProducts = this.products // .value() // .filter((product) => // product.title.toLowerCase().includes(query.toLowerCase()), // ); // this.filteredProducts.set(filteredProducts); // } columns = ['id', 'title', 'price', 'cover', 'actions']; }
<div class="flex flex-col h-screen"> <app-navbar></app-navbar> <div class="w-full grow bgwhite p-6"> <h1 class="text-xl text-gray-700 font-semibold italic mb-5">Table</h2> <input type="search" [formControl]="input" /> <table class="w-full text-sm text-left rtl:text-right text-gray-500" cdk-table [dataSource]="filteredProducts()" > <tr cdk-header-row class="text-xs text-gray-700 uppercase bg-gray-50" *cdkHeaderRowDef="columns" ></tr> <tr cdk-row class="bg-white border-b dark:bg-gray-800" [ngClass]="{ 'bg-white': row.price >= 50, 'bg-red-200': row.price < 50, }" *cdkRowDef="let row; columns: columns" ></tr> <tr cdk-footer-row class="text-xl text-gray-700 uppercase bg-gray-200" *cdkFooterRowDef="columns" ></tr> <!-- id --> <ng-container cdkColumnDef="id"> <th class="px-6 py-3" cdk-header-cell *cdkHeaderCellDef>Id.</th> <td class="px-6 py-4" cdk-cell *cdkCellDef="let row">{{ row.id }}</td> <td class="px-6 py-3" cdk-footer-cell *cdkFooterCellDef></td> </ng-container> <!-- title --> <ng-container cdkColumnDef="title"> <th class="px-6 py-3" cdk-header-cell *cdkHeaderCellDef>Title</th> <td class="px-6 py-4" cdk-cell *cdkCellDef="let row"> {{ row.title }} </td> <td class="px-6 py-3" cdk-footer-cell *cdkFooterCellDef></td> </ng-container> <!-- price --> <ng-container cdkColumnDef="price"> <th class="px-6 py-3" cdk-header-cell *cdkHeaderCellDef>Price</th> <td class="px-6 py-4" cdk-cell *cdkCellDef="let row"> {{ row.price }} </td> <td class="px-6 py-3" cdk-footer-cell *cdkFooterCellDef> {{ totalPrice() }} </td> </ng-container> <!-- cover --> <ng-container cdkColumnDef="cover"> <th class="px-6 py-3" cdk-header-cell *cdkHeaderCellDef>Cover</th> <td class="px-6 py-4" cdk-cell *cdkCellDef="let row"> <img class="w-20" [src]="row.images[0]" [alt]="row.title" /> </td> <td class="px-6 py-3" cdk-footer-cell *cdkFooterCellDef></td> </ng-container> <!-- actions --> <ng-container cdkColumnDef="actions"> <th class="px-6 py-3" cdk-header-cell *cdkHeaderCellDef>Actions</th> <td class="px-6 py-4" cdk-cell *cdkCellDef="let row"> <app-btn (click)="update(row)">Update</app-btn> </td> <td class="px-6 py-3" cdk-footer-cell *cdkFooterCellDef></td> </ng-container> </table> </div> </div>
Agregarf filtros para mapear el valor e igualarlo segun el parametros
find(query: string){ const newProducts = this.originalData.filter( (item) => item.title.toLowerCase().includes(query.toLowerCase()) || item.id.toString().includes(query) || item.price.toString().includes(query) ); }
Mi solucion al reto fue :
const newProducts=this.originalData.filter(element=>element.description.toLowerCase().includes(query.toLocaleLowerCase())|| element.price.toString()===query);
en la interface product defini number como number al igualarlo con query que es de tipo string causaba error ,con toString lo transformo y funciona correctamente