From 928e06290e3c2909e7a8c8b0d8f066b85845dc6a Mon Sep 17 00:00:00 2001 From: chrismclarke Date: Fri, 9 Feb 2024 09:09:47 -0800 Subject: [PATCH] feat: data table custom value templates and header formatter --- .../data-table/data-table.component.html | 17 +++++- .../data-table/data-table.component.ts | 61 ++++++++++++++++++- libs/utils/data.ts | 6 ++ 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/libs/shared/src/features/data-table/data-table.component.html b/libs/shared/src/features/data-table/data-table.component.html index b85436fc8..19cf6b8f5 100644 --- a/libs/shared/src/features/data-table/data-table.component.html +++ b/libs/shared/src/features/data-table/data-table.component.html @@ -19,10 +19,23 @@ @for(column of tableOptions.displayColumns; track column){ - - + + + } + string; /** Bind to row click events */ handleRowClick?: (row: any) => void; } +/** + * Simple pipe that allows providing a custom formatter function, + * used to modify cell values in a pure way + */ +@Pipe({ + standalone: true, + name: 'formatValue', +}) +export class FormatValuePipe implements PipeTransform { + transform(value: T, formatter: (v: T) => U) { + if (!formatter) return value; + return formatter(value); + } +} + /** * The `picsa-data-table` component is a lightweight wrapper around `mat-table`, used * to simplify display of basic tables. - * - * By default the table has support for sort, pagination and data search (filter) + * @example + * ``` + * + * ``` + * The table has support for sort, pagination and data search (filter), + * enabled by default and configurable by an options input @see IDataTableOptions + * @example + * ``` + * + * ``` + * The table will display all cell values directly, without any additional formatting + * If needing to render values within a custom template this can be done via `valueTemplates` + * @example + * ``` + * + * + * {{value | modifierPipe}} + * + * + * ``` * * For more advanced use cases such as custom column display prefer to directly use `mat-table` */ @@ -38,6 +84,7 @@ export interface IDataTableOptions { standalone: true, imports: [ CommonModule, + FormatValuePipe, MatButtonModule, MatFormFieldModule, MatIconModule, @@ -56,6 +103,13 @@ export class PicsaDataTableComponent implements OnChanges { /** User option overrides */ @Input() options: IDataTableOptions = {}; + /** + * Optional references to display specific column values in a custom template, + * indexed by column name. E.g. `{colA: myCustomTemplate}` + * https://angular.io/guide/content-projection#conditional-content-projection + */ + @Input() valueTemplates: Record> = {}; + @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; @@ -66,6 +120,7 @@ export class PicsaDataTableComponent implements OnChanges { search: true, sort: true, handleRowClick: () => null, + formatHeader: (v) => v.split('_').map(capitalise).join(' '), }; public dataSource: MatTableDataSource; diff --git a/libs/utils/data.ts b/libs/utils/data.ts index 226c4e398..7ff664814 100644 --- a/libs/utils/data.ts +++ b/libs/utils/data.ts @@ -84,3 +84,9 @@ export function jsonNestedProperty(obj: any, nestedPath: string) { export function base64ToBlob(base64String, mimetype: string) { return createBlobFromBase64(base64String, mimetype); } + +/** Capitalise the first letter of a string */ +export function capitalise(str: string) { + if (typeof str !== 'string') return str; + return str.charAt(0).toUpperCase() + str.slice(1); +}
{{ column }}{{ el[column] }}{{ column | formatValue: tableOptions.formatHeader }} + @if(valueTemplates[column]){ + + + } @else { + + {{ el[column] }} + } +