Skip to content

Commit

Permalink
feat(cdk/table): add element offsets to sticky styler state (#21886)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelJamesParsons authored Feb 23, 2021
1 parent 3a50c41 commit c42ece3
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/cdk/table/sticky-position-listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ export const STICKY_POSITIONING_LISTENER =
new InjectionToken<StickyPositioningListener>('CDK_SPL');

export type StickySize = number|null|undefined;
export type StickyOffset = number|null|undefined;

export interface StickyUpdate {
elements?: ReadonlyArray<HTMLElement[]|undefined>;
offsets?: StickyOffset[];
sizes: StickySize[];
}

Expand Down
7 changes: 3 additions & 4 deletions src/cdk/table/sticky-styler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,11 @@ export class StickyStyler {
const stickyCellHeights: (number|undefined)[] = [];
const elementsToStick: HTMLElement[][] = [];
for (let rowIndex = 0, stickyOffset = 0; rowIndex < rows.length; rowIndex++) {
stickyOffsets[rowIndex] = stickyOffset;

if (!states[rowIndex]) {
continue;
}

stickyOffsets[rowIndex] = stickyOffset;
const row = rows[rowIndex];
elementsToStick[rowIndex] = this._isNativeHtmlTable ?
Array.from(row.children) as HTMLElement[] : [row];
Expand Down Expand Up @@ -224,10 +223,10 @@ export class StickyStyler {

if (position === 'top') {
this._positionListener?.stickyHeaderRowsUpdated(
{sizes: stickyCellHeights, elements: elementsToStick});
{sizes: stickyCellHeights, offsets: stickyOffsets, elements: elementsToStick});
} else {
this._positionListener?.stickyFooterRowsUpdated(
{sizes: stickyCellHeights, elements: elementsToStick});
{sizes: stickyCellHeights, offsets: stickyOffsets, elements: elementsToStick});
}
});
}
Expand Down
116 changes: 84 additions & 32 deletions src/cdk/table/table.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -922,18 +922,26 @@ describe('CdkTable', () => {
undefined,
headerRows[2].getBoundingClientRect().height,
],
offsets: [
0,
undefined,
headerRows[0].getBoundingClientRect().height,
],
elements: [[headerRows[0]], undefined, [headerRows[2]]],
});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});

component.stickyHeaders = [];
fixture.detectChanges();
flushMicrotasks();
expectNoStickyStyles(headerRows);
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand All @@ -949,13 +957,15 @@ describe('CdkTable', () => {
expectNoStickyStyles([footerRows[1]]);
expectStickyStyles(footerRows[2], '10', {bottom: '0px'});
expectStickyBorderClass(footerRows[2]);
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({
sizes: [
footerRows[2].getBoundingClientRect().height,
undefined,
footerRows[0].getBoundingClientRect().height,
],
offsets: [0, undefined, footerRows[0].getBoundingClientRect().height],
elements: [[footerRows[2]], undefined, [footerRows[0]]],
});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
Expand All @@ -965,8 +975,10 @@ describe('CdkTable', () => {
fixture.detectChanges();
flushMicrotasks();
expectNoStickyStyles(footerRows);
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1010,8 +1022,10 @@ describe('CdkTable', () => {
expectStickyBorderClass(cells[2], {left: true});
expectNoStickyStyles([cells[1], cells[3], cells[4], cells[5]]);
});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({
sizes: [
getCells(dataRows[0])[0].getBoundingClientRect().width,
Expand All @@ -1028,8 +1042,10 @@ describe('CdkTable', () => {
headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row)));
dataRows.forEach(row => expectNoStickyStyles(getCells(row)));
footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row)));
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1063,8 +1079,10 @@ describe('CdkTable', () => {
expectStickyBorderClass(cells[3], {right: true});
expectNoStickyStyles([cells[0], cells[1], cells[2], cells[4]]);
});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({
sizes: [
Expand All @@ -1080,8 +1098,10 @@ describe('CdkTable', () => {
headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row)));
dataRows.forEach(row => expectNoStickyStyles(getCells(row)));
footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row)));
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1169,10 +1189,12 @@ describe('CdkTable', () => {

expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({
sizes: [headerRows[0].getBoundingClientRect().height],
offsets: [0],
elements: [[headerRows[0]]],
});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({
sizes: [footerRows[2].getBoundingClientRect().height],
offsets: [0],
elements: [[footerRows[2]]],
});
expect(component.mostRecentStickyColumnsUpdate).toEqual({
Expand All @@ -1193,8 +1215,10 @@ describe('CdkTable', () => {
dataRows.forEach(row => expectNoStickyStyles([row, ...getCells(row)]));
footerRows.forEach(row => expectNoStickyStyles([row, ...getFooterCells(row)]));

expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1235,9 +1259,15 @@ describe('CdkTable', () => {
undefined,
headerRows[2].getBoundingClientRect().height,
],
offsets: [
0,
undefined,
headerRows[0].getBoundingClientRect().height,
],
elements: [getHeaderCells(headerRows[0]), undefined, getHeaderCells(headerRows[2])],
});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});

Expand All @@ -1246,8 +1276,10 @@ describe('CdkTable', () => {
flushMicrotasks();
expectNoStickyStyles(headerRows); // No sticky styles on rows for native table
headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row)));
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand All @@ -1268,13 +1300,19 @@ describe('CdkTable', () => {
});
expectNoStickyStyles(getFooterCells(footerRows[1]));
expectNoStickyStyles(footerRows); // No sticky styles on rows for native table
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({
sizes: [
footerRows[2].getBoundingClientRect().height,
undefined,
footerRows[0].getBoundingClientRect().height,
],
offsets: [
0,
undefined,
footerRows[2].getBoundingClientRect().height,
],
elements: [getFooterCells(footerRows[2]), undefined, getFooterCells(footerRows[0])],
});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
Expand All @@ -1285,8 +1323,10 @@ describe('CdkTable', () => {
flushMicrotasks();
expectNoStickyStyles(footerRows); // No sticky styles on rows for native table
footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row)));
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1339,8 +1379,10 @@ describe('CdkTable', () => {
expectStickyBorderClass(cells[2], {left: true});
expectNoStickyStyles([cells[1], cells[3], cells[4], cells[5]]);
});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({
sizes: [
getCells(dataRows[0])[0].getBoundingClientRect().width,
Expand All @@ -1356,8 +1398,10 @@ describe('CdkTable', () => {
headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row)));
dataRows.forEach(row => expectNoStickyStyles(getCells(row)));
footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row)));
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1391,8 +1435,10 @@ describe('CdkTable', () => {
expectStickyBorderClass(cells[3], {right: true});
expectNoStickyStyles([cells[0], cells[1], cells[2], cells[4]]);
});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({
sizes: [
Expand All @@ -1408,8 +1454,10 @@ describe('CdkTable', () => {
headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row)));
dataRows.forEach(row => expectNoStickyStyles(getCells(row)));
footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row)));
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down Expand Up @@ -1464,10 +1512,12 @@ describe('CdkTable', () => {

expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({
sizes: [headerRows[0].getBoundingClientRect().height],
offsets: [0],
elements: [getHeaderCells(headerRows[0])],
});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({
sizes: [footerRows[2].getBoundingClientRect().height],
offsets: [0],
elements: [getFooterCells(footerRows[2])],
});
expect(component.mostRecentStickyColumnsUpdate).toEqual({
Expand All @@ -1488,8 +1538,10 @@ describe('CdkTable', () => {
dataRows.forEach(row => expectNoStickyStyles([row, ...getCells(row)]));
footerRows.forEach(row => expectNoStickyStyles([row, ...getFooterCells(row)]));

expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual({sizes: [], elements: []});
expect(component.mostRecentStickyHeaderRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyFooterRowsUpdate).toEqual(
{sizes: [], offsets: [], elements: []});
expect(component.mostRecentStickyColumnsUpdate).toEqual({sizes: []});
expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []});
}));
Expand Down
3 changes: 3 additions & 0 deletions tools/public_api_guard/cdk/table.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ export declare const STICKY_POSITIONING_LISTENER: InjectionToken<StickyPositioni

export declare type StickyDirection = 'top' | 'bottom' | 'left' | 'right';

export declare type StickyOffset = number | null | undefined;

export interface StickyPositioningListener {
stickyColumnsUpdated(update: StickyUpdate): void;
stickyEndColumnsUpdated(update: StickyUpdate): void;
Expand All @@ -359,6 +361,7 @@ export declare class StickyStyler {

export interface StickyUpdate {
elements?: ReadonlyArray<HTMLElement[] | undefined>;
offsets?: StickyOffset[];
sizes: StickySize[];
}

Expand Down

0 comments on commit c42ece3

Please sign in to comment.