Skip to content

Commit c15e307

Browse files
andrewseguinjosephperrott
authored andcommitted
feat(table): enable multiple data rows (#11116)
1 parent fbf06bb commit c15e307

File tree

14 files changed

+711
-102
lines changed

14 files changed

+711
-102
lines changed

src/cdk/table/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ ng_module(
99
module_name = "@angular/cdk/table",
1010
deps = [
1111
"//src/cdk/collections",
12+
"//src/cdk/coercion",
1213
"@rxjs",
1314
],
1415
tsconfig = "//src/cdk:tsconfig-build.json",

src/cdk/table/render-rows.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Rendering Data Rows
2+
3+
The table's primary responsibility is to render rows of cells. The types of rows that may be rendered are header,
4+
footer, and data rows. This document focuses on how the table tries to efficienctly render the data rows.
5+
6+
## Background
7+
8+
Each table's template is defined as a set of row and column templates. The row template defines the template that should
9+
be rendered for a header, footer, or data row. The column templates include the cell templates that will be inserted
10+
into each rendered row.
11+
12+
Each data object may be rendered with one or more row templates. When new data in provided to the table, the table
13+
determines which rows need to be rendered. In order to be efficient, the table attempts to understand how the new list
14+
of rendered rows differs from the previous list of rendered rows so that it can re-use the current list of rendered rows
15+
if possible.
16+
17+
## Rendering
18+
19+
Each time data is provided, the table needs to create the list of rows that will be rendered and keep track of which
20+
data object will be provided as context for each row. For each item in the list, this pair is combined into an object
21+
that uses the `RenderRow` interface. The interface also helps keep track of the data object's index in the provided
22+
data array input.
23+
24+
```ts
25+
export interface RenderRow<T> {
26+
data: T;
27+
dataIndex: number;
28+
rowDef: CdkRowDef<T>;
29+
}
30+
```
31+
32+
When possible, `RenderRow` objects are re-used from the previous rendering. That is, if a particular data object and row
33+
template pairing was previously rendered, it should be used for the new list as well. This makes sure that the
34+
differ can use check-by-reference logic to find the changes between two lists. Note that if a `RenderRow` object is
35+
reused, it should be updated with the correct data index, in case it has moved since last used.
36+
37+
Once the list of `RenderRow` objects has been created, it should be compared to the previous list of `RenderRow`
38+
objects to find the difference in terms of inserts/deletions/moves. This is trivially done using the `IterableDiffer`
39+
logic provided by Angular Core.
40+
41+
Finally, the table uses the list of operations and manipulates the rows through add/remove/move operations.
42+
43+
## Caching `RenderRow` objects
44+
45+
Each `RenderRow` should be cached such that it is a constant-time lookup and retrieval based on the data object and
46+
row template pairing.
47+
48+
In order to achieve this, the cache is built as a map of maps where the key of the outer map is the data object and
49+
the key of the inner map is the row template. The value of the inner map should be an array of the matching cached
50+
`RenderRow` objects that were previously rendered.
51+

src/cdk/table/row.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,12 @@ export class CdkRowDef<T> extends BaseRowDef {
130130
}
131131
}
132132

133-
/** Context provided to the row cells */
133+
/** Context provided to the row cells when `multiTemplateDataRows` is false */
134134
export interface CdkCellOutletRowContext<T> {
135135
/** Data for the row that this cell is located within. */
136136
$implicit?: T;
137137

138-
/** Index location of the row that this cell is located within. */
138+
/** Index of the data object in the provided data array. */
139139
index?: number;
140140

141141
/** Length of the number of total rows. */
@@ -154,6 +154,37 @@ export interface CdkCellOutletRowContext<T> {
154154
odd?: boolean;
155155
}
156156

157+
/**
158+
* Context provided to the row cells when `multiTemplateDataRows` is true. This context is the same
159+
* as CdkCellOutletRowContext except that the single `index` value is replaced by `dataIndex` and
160+
* `renderIndex`.
161+
*/
162+
export interface CdkCellOutletMultiRowContext<T> {
163+
/** Data for the row that this cell is located within. */
164+
$implicit?: T;
165+
166+
/** Index of the data object in the provided data array. */
167+
dataIndex?: number;
168+
169+
/** Index location of the rendered row that this cell is located within. */
170+
renderIndex?: number;
171+
172+
/** Length of the number of total rows. */
173+
count?: number;
174+
175+
/** True if this cell is contained in the first row. */
176+
first?: boolean;
177+
178+
/** True if this cell is contained in the last row. */
179+
last?: boolean;
180+
181+
/** True if this cell is contained in a row with an even-numbered index. */
182+
even?: boolean;
183+
184+
/** True if this cell is contained in a row with an odd-numbered index. */
185+
odd?: boolean;
186+
}
187+
157188
/**
158189
* Outlet for rendering cells inside of a row or header row.
159190
* @docs-private

src/cdk/table/table-errors.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ export function getTableMultipleDefaultRowDefsError() {
3535
* Returns an error to be thrown when there are no matching row defs for a particular set of data.
3636
* @docs-private
3737
*/
38-
export function getTableMissingMatchingRowDefError() {
39-
return Error(`Could not find a matching row definition for the provided row data.`);
38+
export function getTableMissingMatchingRowDefError(data: any) {
39+
return Error(`Could not find a matching row definition for the` +
40+
`provided row data: ${JSON.stringify(data)}`);
4041
}
4142

4243
/**

0 commit comments

Comments
 (0)