package.src.utils.getGroupedRowModel.ts Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of table-core Show documentation
Show all versions of table-core Show documentation
Headless UI for building powerful tables & datagrids for TS/JS.
The newest version!
import { createRow } from '../core/row'
import { Table, Row, RowModel, RowData } from '../types'
import { flattenBy, memo } from '../utils'
export function getGroupedRowModel(): (
table: Table
) => () => RowModel {
return table =>
memo(
() => [table.getState().grouping, table.getPreGroupedRowModel()],
(grouping, rowModel) => {
if (!rowModel.rows.length || !grouping.length) {
return rowModel
}
// Filter the grouping list down to columns that exist
const existingGrouping = grouping.filter(columnId =>
table.getColumn(columnId)
)
const groupedFlatRows: Row[] = []
const groupedRowsById: Record> = {}
// const onlyGroupedFlatRows: Row[] = [];
// const onlyGroupedRowsById: Record = {};
// const nonGroupedFlatRows: Row[] = [];
// const nonGroupedRowsById: Record = {};
// Recursively group the data
const groupUpRecursively = (
rows: Row[],
depth = 0,
parentId?: string
) => {
// Grouping depth has been been met
// Stop grouping and simply rewrite thd depth and row relationships
if (depth >= existingGrouping.length) {
return rows.map(row => {
row.depth = depth
groupedFlatRows.push(row)
groupedRowsById[row.id] = row
if (row.subRows) {
row.subRows = groupUpRecursively(row.subRows, depth + 1, row.id)
}
return row
})
}
const columnId: string = existingGrouping[depth]!
// Group the rows together for this level
const rowGroupsMap = groupBy(rows, columnId)
// Peform aggregations for each group
const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(
([groupingValue, groupedRows], index) => {
let id = `${columnId}:${groupingValue}`
id = parentId ? `${parentId}>${id}` : id
// First, Recurse to group sub rows before aggregation
const subRows = groupUpRecursively(groupedRows, depth + 1, id)
// Flatten the leaf rows of the rows in this group
const leafRows = depth
? flattenBy(groupedRows, row => row.subRows)
: groupedRows
const row = createRow(
table,
id,
leafRows[0]!.original,
index,
depth,
undefined,
parentId
)
Object.assign(row, {
groupingColumnId: columnId,
groupingValue,
subRows,
leafRows,
getValue: (columnId: string) => {
// Don't aggregate columns that are in the grouping
if (existingGrouping.includes(columnId)) {
if (row._valuesCache.hasOwnProperty(columnId)) {
return row._valuesCache[columnId]
}
if (groupedRows[0]) {
row._valuesCache[columnId] =
groupedRows[0].getValue(columnId) ?? undefined
}
return row._valuesCache[columnId]
}
if (row._groupingValuesCache.hasOwnProperty(columnId)) {
return row._groupingValuesCache[columnId]
}
// Aggregate the values
const column = table.getColumn(columnId)
const aggregateFn = column?.getAggregationFn()
if (aggregateFn) {
row._groupingValuesCache[columnId] = aggregateFn(
columnId,
leafRows,
groupedRows
)
return row._groupingValuesCache[columnId]
}
},
})
subRows.forEach(subRow => {
groupedFlatRows.push(subRow)
groupedRowsById[subRow.id] = subRow
// if (subRow.getIsGrouped?.()) {
// onlyGroupedFlatRows.push(subRow);
// onlyGroupedRowsById[subRow.id] = subRow;
// } else {
// nonGroupedFlatRows.push(subRow);
// nonGroupedRowsById[subRow.id] = subRow;
// }
})
return row
}
)
return aggregatedGroupedRows
}
const groupedRows = groupUpRecursively(rowModel.rows, 0)
groupedRows.forEach(subRow => {
groupedFlatRows.push(subRow)
groupedRowsById[subRow.id] = subRow
// if (subRow.getIsGrouped?.()) {
// onlyGroupedFlatRows.push(subRow);
// onlyGroupedRowsById[subRow.id] = subRow;
// } else {
// nonGroupedFlatRows.push(subRow);
// nonGroupedRowsById[subRow.id] = subRow;
// }
})
return {
rows: groupedRows,
flatRows: groupedFlatRows,
rowsById: groupedRowsById,
}
},
{
key: process.env.NODE_ENV === 'development' && 'getGroupedRowModel',
debug: () => table.options.debugAll ?? table.options.debugTable,
onChange: () => {
table._queue(() => {
table._autoResetExpanded()
table._autoResetPageIndex()
})
},
}
)
}
function groupBy(rows: Row[], columnId: string) {
const groupMap = new Map[]>()
return rows.reduce((map, row) => {
const resKey = `${row.getGroupingValue(columnId)}`
const previous = map.get(resKey)
if (!previous) {
map.set(resKey, [row])
} else {
previous.push(row)
}
return map
}, groupMap)
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy