diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 4da5ed4e28..1f4792ea8a 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -115,12 +115,10 @@ } const createFormatter = column => { - if (!column.format?.length) { + if (typeof column.format !== "string" || !column.format.trim().length) { return null } - return row => { - return processStringSync(column.format, { [id]: row }) - } + return row => processStringSync(column.format, { [id]: row }) } const enrichButtons = buttons => { diff --git a/packages/frontend-core/src/components/grid/cells/DataCell.svelte b/packages/frontend-core/src/components/grid/cells/DataCell.svelte index bdf16eab7d..486d9e1952 100644 --- a/packages/frontend-core/src/components/grid/cells/DataCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/DataCell.svelte @@ -40,7 +40,7 @@ // Get the appropriate cell renderer and value $: hasCustomFormat = column.format && !row._isNewRow $: renderer = hasCustomFormat ? TextCell : getCellRenderer(column) - $: value = hasCustomFormat ? column.format(row) : row[column.name] + $: value = hasCustomFormat ? row.__formatted?.[column.name] : row[column.name] // Get the error for this cell if the cell is focused or selected $: error = getErrorStore(rowFocused, cellId) diff --git a/packages/frontend-core/src/components/grid/stores/rows.ts b/packages/frontend-core/src/components/grid/stores/rows.ts index 7e58808327..22357f66a7 100644 --- a/packages/frontend-core/src/components/grid/stores/rows.ts +++ b/packages/frontend-core/src/components/grid/stores/rows.ts @@ -16,6 +16,7 @@ import { Store as StoreContext } from "." interface IndexedUIRow extends UIRow { __idx: number + __formatted: Record } interface RowStore { @@ -114,26 +115,44 @@ export const createStores = (): RowStore => { export const deriveStores = (context: StoreContext): RowDerivedStore => { const { rows, enrichedSchema } = context - // Enrich rows with an index property and any pending changes + // Enrich rows with an index property and additional values const enrichedRows = derived( [rows, enrichedSchema], ([$rows, $enrichedSchema]) => { - const customColumns = Object.values($enrichedSchema || {}).filter( - f => f.related - ) - return $rows.map((row, idx) => ({ - ...row, - __idx: idx, - ...customColumns.reduce>((map, column) => { - const fromField = $enrichedSchema![column.related!.field] - map[column.name] = getRelatedTableValues( - row, - { ...column, related: column.related! }, - fromField - ) - return map - }, {}), - })) + // Find columns which require additional processing + const cols = Object.values($enrichedSchema || {}) + const relatedColumns = cols.filter(col => col.related) + const formattedColumns = cols.filter(col => col.format) + + return $rows.map((row, idx) => { + // Derive any values that need enriched from related rows + const relatedValues = relatedColumns.reduce>( + (map, column) => { + const fromField = $enrichedSchema![column.related!.field] + map[column.name] = getRelatedTableValues( + row, + { ...column, related: column.related! }, + fromField + ) + return map + }, + {} + ) + // Derive any display-only formatted values for this row + const formattedValues = formattedColumns.reduce>( + (map, column) => { + map[column.name] = column.format!(row) + return map + }, + {} + ) + return { + ...row, + ...relatedValues, + __formatted: formattedValues, + __idx: idx, + } + }) } ) @@ -791,6 +810,7 @@ export const createActions = (context: StoreContext): RowActionStore => { let clone: Row = { ...row } delete clone.__idx delete clone.__metadata + delete clone.__formatted if (!get(hasBudibaseIdentifiers) && isGeneratedRowID(clone._id!)) { delete clone._id } diff --git a/packages/types/src/ui/stores/grid/columns.ts b/packages/types/src/ui/stores/grid/columns.ts index aa5124ba04..c6ea801713 100644 --- a/packages/types/src/ui/stores/grid/columns.ts +++ b/packages/types/src/ui/stores/grid/columns.ts @@ -1,10 +1,10 @@ -import { CalculationType, FieldSchema, FieldType } from "@budibase/types" +import { CalculationType, FieldSchema, FieldType, UIRow } from "@budibase/types" export type UIColumn = FieldSchema & { label: string readonly: boolean conditions: any - format?: () => any + format?: (row: UIRow) => any related?: { field: string subField: string diff --git a/packages/types/src/ui/stores/grid/table.ts b/packages/types/src/ui/stores/grid/table.ts index 7b6d659e4c..5eea063084 100644 --- a/packages/types/src/ui/stores/grid/table.ts +++ b/packages/types/src/ui/stores/grid/table.ts @@ -5,6 +5,7 @@ import { RelationSchemaField, SortOrder, Table, + UIRow, UISearchFilter, } from "@budibase/types" @@ -24,9 +25,10 @@ export interface UITable extends Table { export type UIFieldSchema = FieldSchema & BasicViewFieldMetadata & { related?: { field: string; subField: string } - columns?: Record + columns?: Record cellRenderType?: string disabled?: boolean + format?: (row: UIRow) => any } interface UIRelationSchemaField extends RelationSchemaField {