add generic table
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
// dvbooking-cli/src/templates/angular-generic/data-provider.service.ts.tpl
|
||||
|
||||
// Generated by the CLI
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { DataProvider, GetDataOptions, GetDataResponse } from '../../../../components/generic-table/data-provider.interface';
|
||||
import { Product } from '../../models/product.model';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { ProductService } from '../../services/product.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ProductDataProvider implements DataProvider<Product> {
|
||||
private productService = inject(ProductService);
|
||||
|
||||
getData(options?: GetDataOptions): Observable<GetDataResponse<Product>> {
|
||||
const {q,page,limit} = options?.params ?? {};
|
||||
// The generic table's params are compatible with our NestJS Query DTO
|
||||
return this.productService.search(q ?? '',page,limit, ).pipe(
|
||||
map((res) => {
|
||||
// Adapt the paginated response to the GetDataResponse format
|
||||
return { data: res };
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<!-- dvbooking-cli/src/templates/angular-generic/table.component.html.tpl -->
|
||||
|
||||
<!-- Generated by the CLI -->
|
||||
<div class="p-4 md:p-8 space-y-6">
|
||||
<div class="flex justify-between items-center">
|
||||
<h1 class="text-3xl font-bold">Products (Generic Table)</h1>
|
||||
<a routerLink="/products/new" class="btn btn-primary">Create New</a>
|
||||
</div>
|
||||
|
||||
<app-generic-table [config]="tableConfig"></app-generic-table>
|
||||
</div>
|
||||
@@ -0,0 +1,112 @@
|
||||
// dvbooking-cli/src/templates/angular-generic/table.component.ts.tpl
|
||||
|
||||
// Generated by the CLI
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
import { Product } from '../../models/product.model';
|
||||
import { ProductDataProvider } from './product-data-provider.service';
|
||||
import { ColumnDefinition } from '../../../../components/generic-table/column-definition.interface';
|
||||
import { GenericTable } from '../../../../components/generic-table/generic-table';
|
||||
import { GenericTableConfig } from '../../../../components/generic-table/generic-table.config';
|
||||
import {
|
||||
ActionDefinition,
|
||||
GenericActionColumn,
|
||||
} from '../../../../components/generic-action-column/generic-action-column';
|
||||
import { ProductService } from '../../services/product.service';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-table',
|
||||
standalone: true,
|
||||
imports: [GenericTable, RouterModule],
|
||||
templateUrl: './product-table.component.html',
|
||||
})
|
||||
export class ProductTableComponent implements OnInit {
|
||||
|
||||
private refresh$ = new BehaviorSubject<void>(undefined);
|
||||
private filter$ = new BehaviorSubject<any>({});
|
||||
private page$ = new BehaviorSubject<number>(1);
|
||||
private limit$ = new BehaviorSubject<number>(10);
|
||||
|
||||
router = inject(Router);
|
||||
tableConfig!: GenericTableConfig<Product>;
|
||||
|
||||
productDataProvider = inject(ProductDataProvider);
|
||||
productService = inject(ProductService);
|
||||
|
||||
ngOnInit(): void {
|
||||
const actionHandler = (action: ActionDefinition<Product>, item: Product) => {
|
||||
switch (action.action) {
|
||||
case 'view':
|
||||
this.router.navigate(['/products', item?.id]);
|
||||
break;
|
||||
case 'edit':
|
||||
this.router.navigate(['/products', item?.id, 'edit']);
|
||||
break;
|
||||
case 'delete':
|
||||
this.deleteItem(item.id);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
this.tableConfig = {
|
||||
refresh$: this.refresh$,
|
||||
filter$: this.filter$,
|
||||
page$: this.page$,
|
||||
limit$: this.limit$,
|
||||
dataProvider: this.productDataProvider,
|
||||
columns: [
|
||||
{
|
||||
attribute: 'name',
|
||||
headerCell: true,
|
||||
valueCell: true,
|
||||
},
|
||||
{
|
||||
attribute: 'price',
|
||||
headerCell: true,
|
||||
valueCell: true,
|
||||
},
|
||||
{
|
||||
attribute: 'is_available',
|
||||
headerCell: true,
|
||||
valueCell: {
|
||||
value: item => (item as any)?.is_available ? 'yes' : 'no',
|
||||
},
|
||||
},
|
||||
{
|
||||
attribute: 'actions',
|
||||
headerCell: { value: 'Actions' },
|
||||
valueCell: {
|
||||
component: GenericActionColumn,
|
||||
componentInputs: item => ({
|
||||
item: item,
|
||||
actions: [
|
||||
{ action: 'view', handler: actionHandler },
|
||||
{ action: 'edit', handler: actionHandler },
|
||||
{ action: 'delete', handler: actionHandler },
|
||||
] as ActionDefinition<Product>[],
|
||||
}),
|
||||
},
|
||||
},
|
||||
] as ColumnDefinition<Product>[],
|
||||
tableCssClass: 'product-table-container',
|
||||
};
|
||||
}
|
||||
|
||||
deleteItem(id: number): void {
|
||||
if (confirm('Are you sure you want to delete this item?')) {
|
||||
this.productService.remove(id).subscribe({
|
||||
next: () => {
|
||||
console.log(`Item with ID ${id} deleted successfully.`);
|
||||
this.refresh$.next();
|
||||
},
|
||||
// --- THIS IS THE FIX ---
|
||||
// Explicitly type 'err' to satisfy strict TypeScript rules.
|
||||
error: (err: any) => {
|
||||
console.error(`Error deleting item with ID ${id}:`, err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user