Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/clean-aggregate-fallback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@tanstack/alpine-table': patch
'@tanstack/angular-table': patch
'@tanstack/ember-table': patch
'@tanstack/lit-table': patch
'@tanstack/octane-table': patch
'@tanstack/preact-table': patch
'@tanstack/react-table': patch
'@tanstack/solid-table': patch
'@tanstack/svelte-table': patch
'@tanstack/table-core': patch
'@tanstack/vue-table': patch
---

Allow aggregated cells without an `aggregatedCell` renderer to fall back to the column `cell` renderer before using the default aggregate formatter.
9 changes: 2 additions & 7 deletions packages/alpine-table/src/flexRender.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import type {
Cell,
CellData,
Expand Down Expand Up @@ -85,15 +86,9 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDefinition = definition as typeof definition & {
aggregatedCell?: typeof definition.cell
}

if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingDefinition.aggregatedCell ?? definition.cell,
cell.getContext(),
)
return flexRender(getAggregatedCellRender(cell), cell.getContext())
}

if (groupingCell.getIsPlaceholder?.()) {
Expand Down
7 changes: 2 additions & 5 deletions packages/angular-table/src/helpers/flexRenderCell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
RowData,
TableFeatures,
} from '@tanstack/table-core'
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import { FlexViewRenderer } from '../flex-render/renderer'
import type { FlexRenderInputContent } from '../flex-render/renderer'
import type { CellContext, HeaderContext } from '@tanstack/table-core'
Expand Down Expand Up @@ -94,16 +95,12 @@ export class FlexRenderCell<
const header = this.header()
const footer = this.footer()
if (cell) {
const def = cell.column.columnDef
const groupingCell = cell as typeof cell & {
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDef = def as typeof def & {
aggregatedCell?: typeof def.cell
}
if (groupingCell.getIsAggregated?.()) {
return [groupingDef.aggregatedCell ?? def.cell, cell.getContext()]
return [getAggregatedCellRender(cell), cell.getContext()]
}
if (groupingCell.getIsPlaceholder?.()) {
return [null, null]
Expand Down
10 changes: 5 additions & 5 deletions packages/ember-table/src/FlexRender.gts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Component from '@glimmer/component'
import { cached } from '@glimmer/tracking'
import { FlexRenderComponentConfig } from './flex-render-helpers.ts'
import { flexRender } from '@tanstack/table-core/flex-render'
import {
flexRender,
getAggregatedCellRender,
} from '@tanstack/table-core/flex-render'
import type {
Cell_Core,
CellContext,
Expand Down Expand Up @@ -83,13 +86,10 @@ export class FlexRenderCell<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDefinition = definition as typeof definition & {
aggregatedCell?: typeof definition.cell
}

if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingDefinition.aggregatedCell ?? definition.cell,
getAggregatedCellRender(cell),
cell.getContext(),
) as CellRenderResult<TFeatures, TData, TValue>
}
Expand Down
9 changes: 2 additions & 7 deletions packages/lit-table/src/flexRender.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import type {
Cell,
CellData,
Expand Down Expand Up @@ -110,15 +111,9 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingColumnDef = columnDef as typeof columnDef & {
aggregatedCell?: typeof columnDef.cell
}

if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingColumnDef.aggregatedCell ?? columnDef.cell,
cell.getContext(),
)
return flexRender(getAggregatedCellRender(cell), cell.getContext())
}

if (groupingCell.getIsPlaceholder?.()) {
Expand Down
9 changes: 2 additions & 7 deletions packages/octane-table/src/FlexRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// builds the descriptor directly), so this file stays a normal `.ts` module and
// needs no `.tsrx.d.ts` sidecar.
import { createElement } from 'octane'
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import type { CellData, RowData, TableFeatures } from '@tanstack/table-core'
import type { OctaneNode } from 'octane'
import type { FlexRenderProps, Renderable } from './types'
Expand Down Expand Up @@ -65,14 +66,8 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDef = def as typeof def & {
aggregatedCell?: typeof def.cell
}
if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingDef.aggregatedCell ?? def.cell,
cell.getContext(),
)
return flexRender(getAggregatedCellRender(cell), cell.getContext())
}
if (groupingCell.getIsPlaceholder?.()) {
return null
Expand Down
9 changes: 2 additions & 7 deletions packages/preact-table/src/FlexRender.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import type {
Cell,
CellData,
Expand Down Expand Up @@ -121,14 +122,8 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDef = def as typeof def & {
aggregatedCell?: typeof def.cell
}
if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingDef.aggregatedCell ?? def.cell,
cell.getContext(),
)
return flexRender(getAggregatedCellRender(cell), cell.getContext())
}
if (groupingCell.getIsPlaceholder?.()) {
return null
Expand Down
9 changes: 2 additions & 7 deletions packages/react-table/src/FlexRender.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import type {
Cell,
CellData,
Expand Down Expand Up @@ -106,14 +107,8 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDef = def as typeof def & {
aggregatedCell?: typeof def.cell
}
if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingDef.aggregatedCell ?? def.cell,
cell.getContext(),
)
return flexRender(getAggregatedCellRender(cell), cell.getContext())
}
if (groupingCell.getIsPlaceholder?.()) {
return null
Expand Down
9 changes: 2 additions & 7 deletions packages/solid-table/src/FlexRender.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Match, Show, Switch, createComponent } from 'solid-js'
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import type { JSX } from 'solid-js'
import type {
Cell,
Expand Down Expand Up @@ -102,9 +103,6 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDef = def as typeof def & {
aggregatedCell?: typeof def.cell
}

return (
<Show
Expand All @@ -115,10 +113,7 @@ export function FlexRender<
</Show>
}
>
{flexRender(
groupingDef.aggregatedCell ?? def.cell,
c.getContext(),
)}
{flexRender(getAggregatedCellRender(c), c.getContext())}
</Show>
)
}}
Expand Down
6 changes: 2 additions & 4 deletions packages/svelte-table/src/FlexRender.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
generics="TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData"
>
import { isFunction } from '@tanstack/table-core'
import { getAggregatedCellRender } from '@tanstack/table-core/flex-render'
import {
RenderComponentConfig,
RenderSnippetConfig,
Expand Down Expand Up @@ -66,11 +67,8 @@
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingColumnDef = columnDef as typeof columnDef & {
aggregatedCell?: typeof columnDef.cell
}
const content = groupingCell.getIsAggregated?.()
? (groupingColumnDef.aggregatedCell ?? columnDef.cell)
? getAggregatedCellRender(props.cell)
: groupingCell.getIsPlaceholder?.()
? undefined
: columnDef.cell
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { callMemoOrStaticFn, makeObjectMap } from '../../utils'
import { table_getOrderColumnsFn } from '../../features/column-ordering/columnOrderingFeature.utils'
import { constructColumn } from './constructColumn'
import { defaultColumnCell } from './defaultColumnCell'
import type { Table_Internal } from '../../types/Table'
import type { CellData, RowData } from '../../types/type-utils'
import type { TableFeatures } from '../../types/TableFeatures'
Expand Down Expand Up @@ -98,7 +99,7 @@ export function table_getDefaultColumnDef<

return null
},
cell: (props) => props.renderValue<any>()?.toString?.() ?? null,
cell: defaultColumnCell,
...Object.values(table._features).reduce((obj, feature) => {
return Object.assign(obj, feature.getDefaultColumnDef?.())
}, {}),
Expand Down
3 changes: 3 additions & 0 deletions packages/table-core/src/core/columns/defaultColumnCell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const defaultColumnCell = (props: {
renderValue: <TTValue = unknown>() => TTValue
}) => props.renderValue<any>()?.toString?.() ?? null
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
column_getAggregationFns,
column_getAggregationValue,
column_getAutoAggregationFn,
formatAggregatedCellValue,
} from './rowAggregationFeature.utils'
import type { TableFeature } from '../../types/TableFeatures'

Expand All @@ -13,8 +12,6 @@ import type { TableFeature } from '../../types/TableFeatures'
*/
export const rowAggregationFeature: TableFeature = {
getDefaultColumnDef: () => ({
aggregatedCell: ({ column, getValue }: any) =>
formatAggregatedCellValue(getValue(), column.columnDef.aggregationFn),
aggregationFn: 'auto',
maxAggregationDepth: 0,
}),
Expand Down
55 changes: 48 additions & 7 deletions packages/table-core/src/flex-render.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import { defaultColumnCell } from './core/columns/defaultColumnCell'
import { formatAggregatedCellValue } from './features/row-aggregation/rowAggregationFeature.utils'
import type { CellContext } from './core/cells/coreCellsFeature.types'
import type { Cell } from './types/Cell'
import type { ColumnDefTemplate } from './types/ColumnDef'
import type { Header } from './types/Header'
import type { TableFeatures } from './types/TableFeatures'
import type { CellData, RowData } from './types/type-utils'

interface AggregatedCellRenderCell<
TFeatures extends TableFeatures,
TData extends RowData,
TValue extends CellData,
> {
column: {
columnDef: {
cell?: ColumnDefTemplate<CellContext<TFeatures, TData, TValue>>
}
}
getContext: () => CellContext<TFeatures, TData, TValue>
}

/**
* Renders a static value or render function with the provided props.
*
Expand All @@ -21,6 +38,36 @@ export function flexRender<TProps extends object>(
return comp
}

export function getAggregatedCellRender<
TFeatures extends TableFeatures,
TData extends RowData,
TValue extends CellData = CellData,
>(
cell: AggregatedCellRenderCell<TFeatures, TData, TValue>,
): ColumnDefTemplate<CellContext<TFeatures, TData, TValue>> {
const def = cell.column.columnDef
const groupingDef = def as typeof def & {
aggregatedCell?: ColumnDefTemplate<CellContext<TFeatures, TData, TValue>>
}
const customCell = def.cell === defaultColumnCell ? undefined : def.cell

return (
groupingDef.aggregatedCell ??
customCell ??
((context: CellContext<TFeatures, TData, TValue>) => {
const columnDef = context.column
.columnDef as typeof context.column.columnDef & {
aggregationFn?: unknown
}

return formatAggregatedCellValue(
context.getValue(),
columnDef.aggregationFn,
)
})
)
}

export type FlexRenderProps<
TFeatures extends TableFeatures,
TData extends RowData,
Expand Down Expand Up @@ -65,14 +112,8 @@ export function FlexRender<
getIsAggregated?: () => boolean
getIsPlaceholder?: () => boolean
}
const groupingDef = def as typeof def & {
aggregatedCell?: typeof def.cell
}
if (groupingCell.getIsAggregated?.()) {
return flexRender(
groupingDef.aggregatedCell ?? def.cell,
cell.getContext(),
)
return flexRender(getAggregatedCellRender(cell), cell.getContext())
}
if (groupingCell.getIsPlaceholder?.()) {
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
rowExpandingFeature,
rowSelectionFeature,
} from '../../../../src'
import { FlexRender } from '../../../../src/flex-render'
import { testFeatures } from '../../../fixtures/features'
import type { ColumnDef } from '../../../../src'

Expand Down Expand Up @@ -601,12 +602,7 @@ describe('aggregation and grouping integration', () => {
.getAllCells()
.find((cell) => cell.column.id === 'amount')!
expect(amountCell.getIsAggregated()).toBe(true)
const defaultAggregatedCell = amountCell.column.columnDef.aggregatedCell
expect(
typeof defaultAggregatedCell === 'function'
? defaultAggregatedCell(amountCell.getContext())
: defaultAggregatedCell,
).toContain('sum: 130')
expect(FlexRender({ cell: amountCell })).toContain('sum: 130')
expect(
region
.getAllCells()
Expand Down
Loading