@guiexpert/table 1.1.93 → 1.1.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/css/main.css +142 -0
- package/css/table-classes.css +34 -0
- package/css/table-color-vars.css +32 -0
- package/css/table-pivot.css +42 -0
- package/css/table-row-group.css +25 -0
- package/css/table-tree.css +9 -0
- package/index.cjs +44 -36
- package/index.d.ts +39 -0
- package/index.js +6247 -3509
- package/lib/table/aggregation/aggregate-internals.d.ts +30 -0
- package/lib/table/aggregation/aggregate-spec.if.d.ts +51 -0
- package/lib/table/aggregation/aggregate.d.ts +58 -0
- package/lib/table/aggregation/aggregator-name.type.d.ts +39 -0
- package/lib/table/aggregation/aggregator.if.d.ts +51 -0
- package/lib/table/aggregation/aggregators.d.ts +37 -0
- package/lib/table/aggregation/create-value-getter.d.ts +18 -0
- package/lib/table/aggregation/selection-aggregates.if.d.ts +35 -0
- package/lib/table/aggregation/value-accessor.type.d.ts +13 -0
- package/lib/table/data/common/row-number-column-def.d.ts +107 -0
- package/lib/table/data/common/row-number-columns.d.ts +17 -0
- package/lib/table/data/common/row-number-options.d.ts +19 -0
- package/lib/table/data/common/row-number-options.if.d.ts +44 -0
- package/lib/table/data/tablemodel/areamodel/aggregate-footer-options.if.d.ts +73 -0
- package/lib/table/data/tablemodel/areamodel/area-model-aggregate-footer.d.ts +145 -0
- package/lib/table/data/tablemodel/areamodel/area-model-cell-groups.d.ts +18 -1
- package/lib/table/data/tablemodel/areamodel/area-model-pivot-footer.d.ts +47 -0
- package/lib/table/data/tablemodel/areamodel/area-model-pivot.d.ts +250 -0
- package/lib/table/data/tablemodel/areamodel/area-model-row-groups.d.ts +314 -0
- package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +14 -0
- package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +39 -0
- package/lib/table/data/tablemodel/areamodel/derived-values-change.if.d.ts +30 -0
- package/lib/table/factory/pivot-factory.d.ts +63 -0
- package/lib/table/factory/pivot-table-model-para.if.d.ts +44 -0
- package/lib/table/factory/row-group-factory.d.ts +70 -0
- package/lib/table/factory/row-group-table-model-para.if.d.ts +66 -0
- package/lib/table/factory/table-factory.d.ts +45 -1
- package/lib/table/instanceof-workaround.d.ts +143 -6
- package/lib/table/pivot/area-model-pivot-header.d.ts +9 -0
- package/lib/table/pivot/pivot-column-def.d.ts +28 -0
- package/lib/table/pivot/pivot-column-info.if.d.ts +25 -0
- package/lib/table/pivot/pivot-config.if.d.ts +58 -0
- package/lib/table/pivot/pivot-internals.d.ts +13 -0
- package/lib/table/pivot/pivot-layout.d.ts +40 -0
- package/lib/table/pivot/pivot-result.d.ts +157 -0
- package/lib/table/pivot/pivot-table-model.d.ts +86 -0
- package/lib/table/pivot/pivot-value.type.d.ts +67 -0
- package/lib/table/render-scope.d.ts +61 -4
- package/lib/table/renderer/aggregate-cell-renderer.d.ts +27 -0
- package/lib/table/renderer/row-number-cell-renderer.d.ts +27 -0
- package/lib/table/rowgroup/group-rows-internals.d.ts +14 -0
- package/lib/table/rowgroup/group-rows-options.if.d.ts +13 -0
- package/lib/table/rowgroup/group-rows.d.ts +48 -0
- package/lib/table/rowgroup/row-group-column-def.d.ts +26 -0
- package/lib/table/rowgroup/row-group-column-options.if.d.ts +27 -0
- package/lib/table/rowgroup/row-group-detail-row.d.ts +8 -0
- package/lib/table/rowgroup/row-group-field.type.d.ts +56 -0
- package/lib/table/rowgroup/row-group-internals.d.ts +31 -0
- package/lib/table/rowgroup/row-group-layout.d.ts +13 -0
- package/lib/table/rowgroup/row-group-model-options.if.d.ts +39 -0
- package/lib/table/rowgroup/row-group.d.ts +51 -0
- package/lib/table/rowgroup/row-group.if.d.ts +48 -0
- package/lib/table/selection/selection-aggregator.d.ts +37 -0
- package/lib/table/selection/selection-service.d.ts +7 -0
- package/lib/table/service/convenience-dom.service.d.ts +5 -0
- package/lib/table/table-api.d.ts +112 -1
- package/lib/table/table-scope.d.ts +19 -0
- package/package.json +3 -2
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { AreaModel } from './area-model.js';
|
|
2
|
+
import { AreaModelIf } from './area-model.if.js';
|
|
3
|
+
import { HasDefaultRowHeightIf } from './has-default-row-height-if.js';
|
|
4
|
+
import { ColumnDefIf } from '../column/column-def.if.js';
|
|
5
|
+
import { CellRendererIf } from '../../../renderer/cell-render.if.js';
|
|
6
|
+
import { AggregateFooterConfig, AggregateFooterOptionsIf } from './aggregate-footer-options.if.js';
|
|
7
|
+
import { ResolvedAggregateSpec } from '../../../aggregation/aggregate-internals.js';
|
|
8
|
+
|
|
9
|
+
interface AggregationSource {
|
|
10
|
+
/** changes when the rows change (identity) – undefined: only invalidateDerivedValues() */
|
|
11
|
+
signal: unknown;
|
|
12
|
+
/** the number of rows, cheap (part of the cache key) – undefined: not known without computing the rows */
|
|
13
|
+
length?: number;
|
|
14
|
+
/** the rows (objects) – or, for models without row objects, the number of rows; called on a cache miss only */
|
|
15
|
+
getRows(): ArrayLike<unknown> | number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A ready-made footer with totals (sum, average, count, …) that follow filter and sorting – without an own
|
|
19
|
+
* {@link AreaModel}. One or more total rows; every aggregate belongs to the column with the same **property**
|
|
20
|
+
* (column order, row numbers and the checkbox column don't matter). The easiest way is the factory option
|
|
21
|
+
* `footerAggregates` of {@link TableFactory.createTableModel}.
|
|
22
|
+
*
|
|
23
|
+
* - **Data**: the rows the body shows (`getFilteredRows()`), in a tree all leaves the filter keeps (expanded or not),
|
|
24
|
+
* in other models every row via `getValueAt` of the column. Options `source: "all"` and `getRows` change that.
|
|
25
|
+
* - **Cells**: the value is the raw result (a number stays a number – Excel export, own footer renderers); the text is
|
|
26
|
+
* formatted (`format` of the spec, otherwise {@link formatAggregateValue}). A footer renderer of the column
|
|
27
|
+
* (`rendererMap.footer`) gets the raw value; without it the {@link AggregateCellRenderer} writes the text.
|
|
28
|
+
* - **Label**: `"6 rows"` (or the row's `label`) in the first data column without an aggregate, or in `labelProperty`;
|
|
29
|
+
* screen readers announce it as row header.
|
|
30
|
+
* - **Cache**: computed once per change of the data, not per repaint or scroll frame. The table drops the cache when
|
|
31
|
+
* it filters, sorts, edits, gets `updateCells()` or `tableApi.repaint()` / `repaintHard()` – after changing row
|
|
32
|
+
* objects yourself call `tableApi.repaint()`, as for the cells.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // one line: totals of quantity and total – the label "100,000 rows" goes into the first column without aggregate
|
|
36
|
+
* const tableModel = TableFactory.createTableModel({
|
|
37
|
+
* rows: orders,
|
|
38
|
+
* columnDefs,
|
|
39
|
+
* footerAggregates: { quantity: "sum", total: "sum" }
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // two total rows with own labels, an own body model
|
|
44
|
+
* const footer = new AreaModelAggregateFooter<Order>(() => tableModel.getBodyModel(), columnDefs, [
|
|
45
|
+
* { label: "Sum", aggregates: { quantity: "sum", total: "sum" } },
|
|
46
|
+
* { label: (rowCount: number) => `Ø of ${rowCount}`, aggregates: { quantity: "avg", total: "avg" } }
|
|
47
|
+
* ]);
|
|
48
|
+
* const tableModel = TableFactory.createTableModel({ rows: orders, columnDefs, footerAreaModel: footer });
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* // read the results, e.g. for a title
|
|
52
|
+
* const footer = tableModel.getAreaModel("footer") as AreaModelAggregateFooter<Order>;
|
|
53
|
+
* const { total } = footer.getResults(); // { total: 27481033.5, … }
|
|
54
|
+
*
|
|
55
|
+
* @see {@link aggregateColumns} (the same without a table), {@link TableApi.getSelectionAggregates} (selected cells)
|
|
56
|
+
* @see Training: [Footer totals](https://gui.expert/training/footer-totals/)
|
|
57
|
+
*
|
|
58
|
+
* @since 1.1.94
|
|
59
|
+
* @category Aggregation
|
|
60
|
+
*/
|
|
61
|
+
export declare class AreaModelAggregateFooter<T = any> extends AreaModel implements HasDefaultRowHeightIf {
|
|
62
|
+
private readonly columnDefs;
|
|
63
|
+
/** Marker (works across copies of the core): {@link isAreaModelAggregateFooter}. */
|
|
64
|
+
readonly type = "AreaModelAggregateFooter";
|
|
65
|
+
/** Height of the footer rows in px (`rowHeight` of the options, default 34). */
|
|
66
|
+
defaultRowHeight: number;
|
|
67
|
+
private readonly getBody;
|
|
68
|
+
private readonly options;
|
|
69
|
+
private readonly footerRows;
|
|
70
|
+
private readonly textRenderer;
|
|
71
|
+
private cache?;
|
|
72
|
+
/**
|
|
73
|
+
* @param {AreaModelIf | (() => AreaModelIf)} body - the body model, or a function that returns it (if the footer is
|
|
74
|
+
* created before the table model, e.g. `() => tableModel.getBodyModel()`)
|
|
75
|
+
* @param {ColumnDefIf[]} columnDefs - the column definitions of the table (the same array – columns are found by property)
|
|
76
|
+
* @param {AggregateFooterConfig<T>} config - `{ total: "sum" }` (one row), `[{ label, aggregates }, …]` (several rows)
|
|
77
|
+
* or full {@link AggregateFooterOptionsIf}
|
|
78
|
+
*/
|
|
79
|
+
constructor(body: AreaModelIf | (() => AreaModelIf), columnDefs: ColumnDefIf[], config: AggregateFooterConfig<T>);
|
|
80
|
+
/** The full options of a short configuration. */
|
|
81
|
+
static toOptions<T>(config: AggregateFooterConfig<T>): AggregateFooterOptionsIf<T>;
|
|
82
|
+
getRowCount(): number;
|
|
83
|
+
getRowHeight(_rowIndex: number): number;
|
|
84
|
+
getConstantRowHeight(): number | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Drops the cached results – the next cell read computes them again ({@link AreaModelIf.invalidateDerivedValues}).
|
|
87
|
+
* The table calls it when it filters, sorts, edits, gets `updateCells()` and on `tableApi.repaint()` / `repaintHard()`.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* order.total = 99; // changed outside the table
|
|
91
|
+
* tableApi.repaint(); // the cells and the footer show it
|
|
92
|
+
*/
|
|
93
|
+
invalidateDerivedValues(): void;
|
|
94
|
+
/**
|
|
95
|
+
* The results of a footer row by key (also of keys without a column).
|
|
96
|
+
*
|
|
97
|
+
* @param {number} [rowIndex=0] - the footer row
|
|
98
|
+
* @returns {Record<string, unknown>} key → result (`{}` for a row that does not exist); do not modify it
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const footer = tableModel.getAreaModel("footer") as AreaModelAggregateFooter<Order>;
|
|
102
|
+
* document.title = `${formatAggregateValue(footer.getResults().total)} € in ${footer.getAggregationRowCount()} orders`;
|
|
103
|
+
*/
|
|
104
|
+
getResults(rowIndex?: number): Record<string, unknown>;
|
|
105
|
+
/**
|
|
106
|
+
* The number of aggregated rows (e.g. the filtered body rows; in a tree the leaves).
|
|
107
|
+
*
|
|
108
|
+
* @returns {number} the number of rows the results are based on
|
|
109
|
+
*/
|
|
110
|
+
getAggregationRowCount(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Whether a cell shows the label of its footer row (the table gives it `role="rowheader"`).
|
|
113
|
+
*
|
|
114
|
+
* @param {number} rowIndex - footer row
|
|
115
|
+
* @param {number} columnIndex - column (model index)
|
|
116
|
+
* @returns {boolean} true for the label cell
|
|
117
|
+
*/
|
|
118
|
+
isLabelCell(rowIndex: number, columnIndex: number): boolean;
|
|
119
|
+
getValueAt(rowIndex: number, columnIndex: number): any;
|
|
120
|
+
getTextValueAt(rowIndex: number, columnIndex: number): string;
|
|
121
|
+
/**
|
|
122
|
+
* The renderer of a cell: for a result the footer renderer of the column (it gets the raw value), otherwise – and for
|
|
123
|
+
* the label – an {@link AggregateCellRenderer} that writes {@link getTextValueAt} as text.
|
|
124
|
+
*/
|
|
125
|
+
getCellRenderer(rowIndex: number, columnIndex: number): CellRendererIf | undefined;
|
|
126
|
+
getCustomClassesAt(rowIndex: number, columnIndex: number): string[];
|
|
127
|
+
/** The label column of a footer row, -1 for none. */
|
|
128
|
+
protected getLabelColumnIndex(rowIndex: number): number;
|
|
129
|
+
/** The label text of a footer row. */
|
|
130
|
+
protected getLabel(rowIndex: number): string;
|
|
131
|
+
/**
|
|
132
|
+
* The rows to aggregate: `getRows` of the options, the (filtered) rows of an object body, the leaves of a tree, or –
|
|
133
|
+
* for models without row objects – the row count.
|
|
134
|
+
* @internal
|
|
135
|
+
*/
|
|
136
|
+
protected getSource(): AggregationSource;
|
|
137
|
+
/**
|
|
138
|
+
* The getter of a spec for a model without row objects: a property with a column → `getValueAt` of that column;
|
|
139
|
+
* a function or a path without column → applied to `getRowByIndex(r)`.
|
|
140
|
+
* @internal
|
|
141
|
+
*/
|
|
142
|
+
protected createIndexGetter(body: AreaModelIf, spec: ResolvedAggregateSpec<T>): ((rowIndex: number) => unknown) | undefined;
|
|
143
|
+
private compute;
|
|
144
|
+
}
|
|
145
|
+
export {};
|
|
@@ -15,7 +15,7 @@ import { TableHeaderGroupStateIf } from '../../../state/table-state.if.js';
|
|
|
15
15
|
/** @category Header groups */
|
|
16
16
|
export declare class AreaModelCellGroups implements AreaModelIf {
|
|
17
17
|
readonly areaIdent: AreaIdent;
|
|
18
|
-
|
|
18
|
+
groups: CellGroupIf[];
|
|
19
19
|
columnDefs: ColumnDefIf[];
|
|
20
20
|
readonly defaultRowHeight: number;
|
|
21
21
|
private headerGroupOptions;
|
|
@@ -80,6 +80,23 @@ export declare class AreaModelCellGroups implements AreaModelIf {
|
|
|
80
80
|
* @since 1.1.92
|
|
81
81
|
*/
|
|
82
82
|
setGroupClosed(id: string, closed: boolean): ColumnDefIf[] | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Replaces the header groups (e.g. a pivot table with other column keys): builds the header rows again and returns
|
|
85
|
+
* the column definitions in header order – existing definitions with the same property are kept (width, classes,
|
|
86
|
+
* renderers), their visibility follows the (collapsed) groups. Repaint the table afterwards (a pivot table does all of
|
|
87
|
+
* this in {@link TableApi.setPivotConfig}).
|
|
88
|
+
*
|
|
89
|
+
* @param {CellGroupIf[]} groups - the new groups; every column is a leaf with a `property`
|
|
90
|
+
* @param {ColumnDefIf[]} [columnDefs] - definitions to use for these properties (default: the current ones)
|
|
91
|
+
* @returns {ColumnDefIf[]} the column definitions, one per leaf, in header order
|
|
92
|
+
* @example
|
|
93
|
+
* const header = tableApi.getTableModel().getAreaModel("header") as AreaModelCellGroups;
|
|
94
|
+
* const columnDefs = header.setGroups([
|
|
95
|
+
* { data: "Customer", children: [{ data: "Name", property: "name" }, { data: "City", property: "city" }] }
|
|
96
|
+
* ]);
|
|
97
|
+
* @since 1.1.94
|
|
98
|
+
*/
|
|
99
|
+
setGroups(groups: CellGroupIf[], columnDefs?: ColumnDefIf[]): ColumnDefIf[];
|
|
83
100
|
/** The toggleable groups by id (header order). */
|
|
84
101
|
private getToggleGroups;
|
|
85
102
|
/**
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AreaModel } from './area-model.js';
|
|
2
|
+
import { HasDefaultRowHeightIf } from './has-default-row-height-if.js';
|
|
3
|
+
import { CellRendererIf } from '../../../renderer/cell-render.if.js';
|
|
4
|
+
import { AreaModelPivot } from './area-model-pivot.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The total row of a pivot table: the label `"Total"` in the group column and the column totals (cells, subtotals,
|
|
8
|
+
* grand total) of the {@link AreaModelPivot}. The totals come from the source rows (merged states), never from the
|
|
9
|
+
* displayed rows – an average stays the average of all rows. Created by {@link PivotFactory.createTableModel}
|
|
10
|
+
* (`totalRow: false` → no row).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const footer = tableModel.getAreaModel("footer") as AreaModelPivotFooter;
|
|
14
|
+
* footer.getValueAt(0, pivotModel.getPivotBody().getColumnIndex([])); // 450 – the grand total
|
|
15
|
+
*
|
|
16
|
+
* @since 1.1.94
|
|
17
|
+
* @category Pivot
|
|
18
|
+
*/
|
|
19
|
+
export declare class AreaModelPivotFooter<T = any> extends AreaModel implements HasDefaultRowHeightIf {
|
|
20
|
+
private readonly body;
|
|
21
|
+
defaultRowHeight: number;
|
|
22
|
+
/** Marker (works across copies of the core). */
|
|
23
|
+
readonly type = "AreaModelPivotFooter";
|
|
24
|
+
private readonly textRenderer;
|
|
25
|
+
/**
|
|
26
|
+
* @param {AreaModelPivot<T>} body - the pivot body (its columns and totals)
|
|
27
|
+
* @param {number} [defaultRowHeight=34] - row height in px
|
|
28
|
+
*/
|
|
29
|
+
constructor(body: AreaModelPivot<T>, defaultRowHeight?: number);
|
|
30
|
+
/** 1 – or 0 with `totalRow: false` or without row fields (the body shows the total then). */
|
|
31
|
+
getRowCount(): number;
|
|
32
|
+
getRowHeight(_rowIndex: number): number;
|
|
33
|
+
getConstantRowHeight(): number | undefined;
|
|
34
|
+
getValueAt(rowIndex: number, columnIndex: number): any;
|
|
35
|
+
getTextValueAt(rowIndex: number, columnIndex: number): string;
|
|
36
|
+
getCellRenderer(_rowIndex: number, columnIndex: number): CellRendererIf | undefined;
|
|
37
|
+
getCustomClassesAt(rowIndex: number, columnIndex: number): string[];
|
|
38
|
+
/**
|
|
39
|
+
* True for the label cell ("Total") – the table gives it `role="rowheader"`.
|
|
40
|
+
*
|
|
41
|
+
* @param {number} rowIndex - footer row
|
|
42
|
+
* @param {number} columnIndex - column index
|
|
43
|
+
* @returns {boolean} true for the group column of the total row
|
|
44
|
+
*/
|
|
45
|
+
isRowHeaderCell(rowIndex: number, columnIndex: number): boolean;
|
|
46
|
+
private isLabelColumn;
|
|
47
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { AreaModelTree } from './area-model-tree.js';
|
|
2
|
+
import { ColumnDefIf } from '../column/column-def.if.js';
|
|
3
|
+
import { CellRendererIf } from '../../../renderer/cell-render.if.js';
|
|
4
|
+
import { FilterFunction } from '../../common/filter-function.js';
|
|
5
|
+
import { SortItem } from '../../common/sort-item.js';
|
|
6
|
+
import { RowGroupIf } from '../../../rowgroup/row-group.if.js';
|
|
7
|
+
import { PivotConfigIf } from '../../../pivot/pivot-config.if.js';
|
|
8
|
+
import { PivotColumnInfoIf } from '../../../pivot/pivot-column-info.if.js';
|
|
9
|
+
import { PivotResult } from '../../../pivot/pivot-result.js';
|
|
10
|
+
import { RowGroupColumnOptionsIf } from '../../../rowgroup/row-group-column-options.if.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The body of a pivot table: one row per row group (a tree for several row fields, with subtotals in the group rows),
|
|
14
|
+
* one column per column key × value, plus subtotal and total columns. Created by {@link PivotFactory.createTableModel}
|
|
15
|
+
* – the factory also builds the grouped header and the total row.
|
|
16
|
+
*
|
|
17
|
+
* It is a tree ({@link AreaModelTree}, `isAreaModelTree` is true): rows are tree rows with a {@link RowGroupIf} as
|
|
18
|
+
* `data`; expanding, `tableApi.expandAll()`, keyboard, screen reader attributes and remembering expanded rows work as
|
|
19
|
+
* in a tree table. The cells come from a {@link PivotResult} ({@link getResult}).
|
|
20
|
+
*
|
|
21
|
+
* - **Filter**: `externalFilterFunction` gets your **source objects** (as in a flat table and a row grouping) – it
|
|
22
|
+
* filters before the aggregation; all cells and totals follow. Rows without a matching source row disappear; the
|
|
23
|
+
* columns stay (they come from all rows).
|
|
24
|
+
* - **Sorting**: by a value column → the rows of every level by that value (empty cells last); by the group column →
|
|
25
|
+
* by key. `tableApi.sort(fn)` compares two {@link RowGroupIf}.
|
|
26
|
+
* - Cells are not editable. Changed source data: {@link TableApi.setPivotConfig} with new rows or `tableApi.repaint()` (same
|
|
27
|
+
* keys), new keys or fields: {@link TableApi.setPivotConfig}.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const tableModel = PivotFactory.createTableModel<Sale>({
|
|
31
|
+
* rows: sales, rowFields: ["region"], columnFields: ["monat"], values: ["umsatz"]
|
|
32
|
+
* });
|
|
33
|
+
* const pivotBody = tableModel.getPivotBody();
|
|
34
|
+
* pivotBody.getValueAt(0, pivotBody.getColumnIndex(["Jan"])); // 150 – Nord, Jan
|
|
35
|
+
*
|
|
36
|
+
* @see Training: [Pivot tables](https://gui.expert/training/pivot-tables/)
|
|
37
|
+
*
|
|
38
|
+
* @typeParam T - the row type
|
|
39
|
+
* @since 1.1.94
|
|
40
|
+
* @category Pivot
|
|
41
|
+
*/
|
|
42
|
+
export declare class AreaModelPivot<T = any> extends AreaModelTree<any> {
|
|
43
|
+
/** Marker for {@link isAreaModelPivot} (works across copies of the core). `type` stays `"AreaModelTree"`. */
|
|
44
|
+
readonly kind = "AreaModelPivot";
|
|
45
|
+
private config;
|
|
46
|
+
private sourceRows;
|
|
47
|
+
private result;
|
|
48
|
+
private rowFields;
|
|
49
|
+
private groupColumnOptions;
|
|
50
|
+
private readonly textRenderer;
|
|
51
|
+
private infoByProperty;
|
|
52
|
+
private userFilter?;
|
|
53
|
+
private accepted?;
|
|
54
|
+
private dirty;
|
|
55
|
+
private builds;
|
|
56
|
+
/**
|
|
57
|
+
* @param {T[]} rows - the source rows (not changed)
|
|
58
|
+
* @param {PivotConfigIf<T>} config - row fields, column fields, values
|
|
59
|
+
* @param {Partial<RowGroupColumnOptionsIf<T>>} [groupColumn] - label options of the group column (`showCount`, `label`)
|
|
60
|
+
* @param {number} [defaultRowHeight=34] - row height in px
|
|
61
|
+
*/
|
|
62
|
+
constructor(rows: T[], config: PivotConfigIf<T>, groupColumn?: Partial<RowGroupColumnOptionsIf<T>>, defaultRowHeight?: number);
|
|
63
|
+
/**
|
|
64
|
+
* The current configuration.
|
|
65
|
+
*
|
|
66
|
+
* @returns {PivotConfigIf<T>} a copy
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* pivotBody.getConfig().columnFields; // ["monat"]
|
|
70
|
+
*/
|
|
71
|
+
getConfig(): PivotConfigIf<T>;
|
|
72
|
+
/**
|
|
73
|
+
* The pivot: row and column hierarchies and all values (also subtotals and totals) – for drill-down, own
|
|
74
|
+
* evaluations or a chart next to the table.
|
|
75
|
+
*
|
|
76
|
+
* @returns {PivotResult<T>} the result (do not modify)
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* const result = pivotBody.getResult();
|
|
80
|
+
* result.columnLeaves.map(c => c.label); // ["Jan", "Feb"]
|
|
81
|
+
* result.getValue(); // 450
|
|
82
|
+
*/
|
|
83
|
+
getResult(): PivotResult<T>;
|
|
84
|
+
/**
|
|
85
|
+
* The rows the pivot is built from.
|
|
86
|
+
*
|
|
87
|
+
* @returns {T[]} the source rows (do not modify the array – use `tableApi.setPivotConfig({}, rows)`)
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* pivotBody.getSourceRows().length; // 6
|
|
91
|
+
*/
|
|
92
|
+
getSourceRows(): T[];
|
|
93
|
+
/**
|
|
94
|
+
* Counts how often the pivot was built (start, new configuration, new rows).
|
|
95
|
+
*
|
|
96
|
+
* @returns {number} the number of builds
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const before = pivotBody.getBuildCount();
|
|
100
|
+
*/
|
|
101
|
+
getBuildCount(): number;
|
|
102
|
+
/**
|
|
103
|
+
* Builds the pivot again (keys, rows) – {@link PivotTableModel.setPivotConfig} calls it, followed
|
|
104
|
+
* by the new columns ({@link setColumnDefs}). Expanded rows whose path stays keep their state; the filter stays, the
|
|
105
|
+
* sorting is reset.
|
|
106
|
+
*
|
|
107
|
+
* @param {PivotConfigIf<T>} config - the configuration
|
|
108
|
+
* @param {T[]} [rows] - new source rows (default: the current ones)
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
configure(config: PivotConfigIf<T>, rows?: T[]): void;
|
|
112
|
+
/**
|
|
113
|
+
* Sets the columns (group column, value columns) after a new layout. @internal
|
|
114
|
+
*
|
|
115
|
+
* @param {ColumnDefIf[]} columnDefs - all columns of the table
|
|
116
|
+
*/
|
|
117
|
+
setColumnDefs(columnDefs: ColumnDefIf[]): void;
|
|
118
|
+
/**
|
|
119
|
+
* The property of a column (follows moved columns).
|
|
120
|
+
*
|
|
121
|
+
* @param {number} columnIndex - column index
|
|
122
|
+
* @returns {string | undefined} the property, e.g. {@link RowGroupColumnDef.PROPERTY} for the group column
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* pivotBody.getPropertyAt(0); // "RowGroupColumn"
|
|
126
|
+
*/
|
|
127
|
+
getPropertyAt(columnIndex: number): string | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* The row group of a displayed row.
|
|
130
|
+
*
|
|
131
|
+
* @param {number} rowIndex - index of the displayed body row
|
|
132
|
+
* @returns {RowGroupIf<T> | undefined} the group, undefined for the total row of a pivot without row fields
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* pivotBody.getRowGroup(0)?.path; // ["Nord"]
|
|
136
|
+
*/
|
|
137
|
+
getRowGroup(rowIndex: number): RowGroupIf<T> | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* What a column shows: a column key, a subtotal or a total, and which value.
|
|
140
|
+
*
|
|
141
|
+
* @param {number} columnIndex - column index
|
|
142
|
+
* @returns {PivotColumnInfoIf | undefined} undefined for the group column (and row numbers)
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* pivotBody.getColumnInfo(1)?.column?.label; // "Jan"
|
|
146
|
+
*/
|
|
147
|
+
getColumnInfo(columnIndex: number): PivotColumnInfoIf | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* The property of a value column – for `tableApi.getColumnIndex()`, `sortByColumn()`, `setColumnWidth()` …
|
|
150
|
+
*
|
|
151
|
+
* @param {unknown[]} columnPath - the column keys from the top column field down, e.g. `[2026, 1]`; `[]` = the total column
|
|
152
|
+
* @param {number | string} [value=0] - the index or name of the value
|
|
153
|
+
* @returns {string | undefined} the property, undefined if there is no such column
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* tableApi.sortByColumn(pivotBody.getColumnProperty([])!, "desc"); // rows by their total, largest first
|
|
157
|
+
*/
|
|
158
|
+
getColumnProperty(columnPath: unknown[], value?: number | string): string | undefined;
|
|
159
|
+
/**
|
|
160
|
+
* The index of a value column (see {@link getColumnProperty}).
|
|
161
|
+
*
|
|
162
|
+
* @param {unknown[]} columnPath - the column keys, `[]` = the total column
|
|
163
|
+
* @param {number | string} [value=0] - the index or name of the value
|
|
164
|
+
* @returns {number} the column index or -1
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* pivotBody.getColumnIndex(["Jan"]); // 1
|
|
168
|
+
*/
|
|
169
|
+
getColumnIndex(columnPath: unknown[], value?: number | string): number;
|
|
170
|
+
/**
|
|
171
|
+
* The source rows behind a cell (drill-down): the rows of its row group and column key that the filter keeps.
|
|
172
|
+
*
|
|
173
|
+
* @param {number} rowIndex - index of the displayed body row
|
|
174
|
+
* @param {number} columnIndex - column index (the group column: all rows of the row group)
|
|
175
|
+
* @returns {T[]} a new array in source order
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* pivotBody.getCellSourceRows(0, 1).map(s => s.umsatz); // [100, 50] – Nord, Jan
|
|
179
|
+
*/
|
|
180
|
+
getCellSourceRows(rowIndex: number, columnIndex: number): T[];
|
|
181
|
+
getValueAt(rowIndex: number, columnIndex: number): any;
|
|
182
|
+
getTextValueAt(rowIndex: number, columnIndex: number): string;
|
|
183
|
+
/** Value columns: the {@link AggregateCellRenderer} (text node); the group column: none (label as text). */
|
|
184
|
+
getCellRenderer(_rowIndex: number, columnIndex: number): CellRendererIf | undefined;
|
|
185
|
+
getCustomClassesAt(rowIndex: number, columnIndex: number): string[];
|
|
186
|
+
/**
|
|
187
|
+
* True for the label cell of a row (the table gives it `role="rowheader"`).
|
|
188
|
+
*
|
|
189
|
+
* @param {number} rowIndex - index of the displayed body row
|
|
190
|
+
* @param {number} columnIndex - column index
|
|
191
|
+
* @returns {boolean} true for the group column
|
|
192
|
+
*/
|
|
193
|
+
isRowHeaderCell(rowIndex: number, columnIndex: number): boolean;
|
|
194
|
+
/** Pivot cells are computed – not editable. */
|
|
195
|
+
isEditable(_rowIndex: number, _columnIndex: number): boolean;
|
|
196
|
+
/** Pivot cells are computed – `setValue` does nothing (`false`). */
|
|
197
|
+
setValue(_rowIndex: number, _columnIndex: number, _value: any): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Filters the **source rows** before the aggregation: `predictFn` gets your objects (as in a flat table), index and
|
|
200
|
+
* array of the source rows. All cells and totals follow; rows without a matching source row disappear. Usually
|
|
201
|
+
* called by `tableApi.externalFilterChanged()` with `tableOptions.externalFilterFunction`.
|
|
202
|
+
*
|
|
203
|
+
* @param {FilterFunction<S>} predictFn - returns a truthy value for the rows to count
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* tableOptions.externalFilterFunction = (sale: Sale) => sale.produkt === "A";
|
|
207
|
+
* tableApi.externalFilterChanged(); // Nord: Jan 100, Feb 120 · Süd: Jan 80, Feb 30
|
|
208
|
+
*/
|
|
209
|
+
externalFilterChanged<S>(predictFn: FilterFunction<S>): void;
|
|
210
|
+
/**
|
|
211
|
+
* Sorts the rows of every level: by a value column by its values (empty cells last, in both directions), by the
|
|
212
|
+
* group column by key. A new pivot ({@link TableApi.setPivotConfig}) starts unsorted (the columns are different).
|
|
213
|
+
*
|
|
214
|
+
* @param {SortItem[]} sortItems - primary key first
|
|
215
|
+
* @returns {boolean} false for an empty list
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* pivotBody.doSort([new SortItem(pivotBody.getColumnIndex([]), "desc")]); // by the total, largest first
|
|
219
|
+
* tableApi.repaint();
|
|
220
|
+
*/
|
|
221
|
+
doSort(sortItems: SortItem[]): boolean;
|
|
222
|
+
/**
|
|
223
|
+
* Sorts the rows of every level with your function – it gets two {@link RowGroupIf} (siblings).
|
|
224
|
+
*
|
|
225
|
+
* @param {(a: any, b: any) => number} compareFn - compares two row groups
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* tableApi.sort((a: RowGroupIf, b: RowGroupIf) => b.count - a.count); // most source rows first
|
|
229
|
+
*/
|
|
230
|
+
sort(compareFn: (a: any, b: any) => number): void;
|
|
231
|
+
/**
|
|
232
|
+
* Computes the cells again on the next read – the table calls it after filter, sorting and `tableApi.repaint()`.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* sales[0].umsatz = 999; // changed outside the table
|
|
236
|
+
* tableApi.repaint(); // calls invalidateDerivedValues() – all cells are computed again
|
|
237
|
+
*/
|
|
238
|
+
invalidateDerivedValues(): void;
|
|
239
|
+
private isSubtotalSuppressed;
|
|
240
|
+
/** The label of a row in the group column. */
|
|
241
|
+
protected getGroupLabel(group: RowGroupIf<T>): string;
|
|
242
|
+
private ensureComputed;
|
|
243
|
+
/** The filter result per source row (1 = counted). */
|
|
244
|
+
private acceptedBy;
|
|
245
|
+
private createRowComparator;
|
|
246
|
+
/** (Re)builds the pivot and the tree rows; keeps the expanded state of known row groups and the filter (a new pivot is unsorted). */
|
|
247
|
+
private build;
|
|
248
|
+
private createRow;
|
|
249
|
+
private isExpandedByDefault;
|
|
250
|
+
}
|