From 553cb9e0d713fc755f5c877bedc85e59e223d614 Mon Sep 17 00:00:00 2001 From: Tomi Virkki Date: Wed, 11 Oct 2023 08:52:19 +0300 Subject: [PATCH] feat: grid column header and footer part names (#6629) --- .../grid/src/vaadin-grid-column-mixin.d.ts | 14 +++ packages/grid/src/vaadin-grid-column-mixin.js | 35 ++++++++ packages/grid/test/styling.common.js | 87 +++++++++++++++++++ packages/grid/test/typings/grid.types.ts | 4 + 4 files changed, 140 insertions(+) diff --git a/packages/grid/src/vaadin-grid-column-mixin.d.ts b/packages/grid/src/vaadin-grid-column-mixin.d.ts index e9f53fd050..7e15a7fc07 100644 --- a/packages/grid/src/vaadin-grid-column-mixin.d.ts +++ b/packages/grid/src/vaadin-grid-column-mixin.d.ts @@ -93,6 +93,20 @@ export declare class ColumnBaseMixinClass` element. */ footerRenderer: GridHeaderFooterRenderer | null | undefined; + + /** + * Custom part name for the header cell. + * + * @attr {string} header-part-name + */ + headerPartName: string | null | undefined; + + /** + * Custom part name for the footer cell. + * + * @attr {string} footer-part-name + */ + footerPartName: string | null | undefined; } export interface GridColumnMixin> diff --git a/packages/grid/src/vaadin-grid-column-mixin.js b/packages/grid/src/vaadin-grid-column-mixin.js index 5c1c439daf..85004dbe4a 100644 --- a/packages/grid/src/vaadin-grid-column-mixin.js +++ b/packages/grid/src/vaadin-grid-column-mixin.js @@ -101,6 +101,24 @@ export const ColumnBaseMixin = (superClass) => type: String, }, + /** + * Custom part name for the header cell. + * + * @attr {string} header-part-name + */ + headerPartName: { + type: String, + }, + + /** + * Custom part name for the footer cell. + * + * @attr {string} footer-part-name + */ + footerPartName: { + type: String, + }, + /** * @type {boolean} * @protected @@ -238,6 +256,7 @@ export const ColumnBaseMixin = (superClass) => '_reorderStatusChanged(_reorderStatus, _headerCell, _footerCell, _cells.*)', '_hiddenChanged(hidden, _headerCell, _footerCell, _cells.*)', '_rowHeaderChanged(rowHeader, _cells.*)', + '__headerFooterPartNameChanged(_headerCell, _footerCell, headerPartName, footerPartName)', ]; } @@ -631,6 +650,22 @@ export const ColumnBaseMixin = (superClass) => this._renderHeaderCellContent(headerRenderer, headerCell); } + /** @private */ + __headerFooterPartNameChanged(headerCell, footerCell, headerPartName, footerPartName) { + [ + { cell: headerCell, partName: headerPartName }, + { cell: footerCell, partName: footerPartName }, + ].forEach(({ cell, partName }) => { + if (cell) { + const customParts = cell.__customParts || []; + cell.part.remove(...customParts); + + cell.__customParts = partName ? partName.trim().split(' ') : []; + cell.part.add(...cell.__customParts); + } + }); + } + /** * Renders the content of body cells using a renderer. * diff --git a/packages/grid/test/styling.common.js b/packages/grid/test/styling.common.js index 81349e7267..bc6ce3fd23 100644 --- a/packages/grid/test/styling.common.js +++ b/packages/grid/test/styling.common.js @@ -197,4 +197,91 @@ describe('styling', () => { runStylingTest('parts', 'cellPartNameGenerator', 'generateCellPartNames', assertPartNames); }); + + describe('header and footer part name', () => { + let column; + let headerCell; + let footerCell; + + beforeEach(() => { + column = grid.querySelector('vaadin-grid-column'); + column.footerRenderer = (root) => { + root.textContent = 'footer'; + }; + headerCell = getContainerCell(grid.$.header, 0, 0); + footerCell = getContainerCell(grid.$.footer, 0, 0); + }); + + it('should add a header and footer part name', () => { + column.headerPartName = 'foobar'; + column.footerPartName = 'bazqux'; + + expect(headerCell.getAttribute('part')).to.contain('foobar'); + expect(footerCell.getAttribute('part')).to.contain('bazqux'); + }); + + it('should clear the header and footer part name', () => { + column.headerPartName = 'foobar'; + column.footerPartName = 'bazqux'; + + column.headerPartName = ''; + column.footerPartName = ''; + + expect(headerCell.getAttribute('part')).to.not.contain('foobar'); + expect(footerCell.getAttribute('part')).to.not.contain('bazqux'); + }); + + it('should add multiple header and footer part names', () => { + column.headerPartName = 'foobar bazqux'; + column.footerPartName = 'bazqux foobar'; + + expect(headerCell.getAttribute('part')).to.contain('foobar'); + expect(headerCell.getAttribute('part')).to.contain('bazqux'); + expect(footerCell.getAttribute('part')).to.contain('foobar'); + expect(footerCell.getAttribute('part')).to.contain('bazqux'); + }); + + it('should remove one header and footer part name', () => { + column.headerPartName = 'foobar bazqux'; + column.footerPartName = 'bazqux foobar'; + + column.headerPartName = 'foobar'; + column.footerPartName = 'bazqux'; + + expect(headerCell.getAttribute('part')).to.contain('foobar'); + expect(headerCell.getAttribute('part')).to.not.contain('bazqux'); + expect(footerCell.getAttribute('part')).to.contain('bazqux'); + expect(footerCell.getAttribute('part')).to.not.contain('foobar'); + }); + + it('should add a header and footer part name with trailing whitespace', () => { + column.headerPartName = 'foobar '; + column.footerPartName = ' bazqux'; + + expect(headerCell.getAttribute('part')).to.contain('foobar'); + expect(footerCell.getAttribute('part')).to.contain('bazqux'); + }); + + it('should clear the header and footer part name with null', () => { + column.headerPartName = 'foobar'; + column.footerPartName = 'bazqux'; + + column.headerPartName = null; + column.footerPartName = null; + + expect(headerCell.getAttribute('part')).to.not.contain('foobar'); + expect(footerCell.getAttribute('part')).to.not.contain('bazqux'); + }); + + it('should clear the header and footer part name with undefined', () => { + column.headerPartName = 'foobar'; + column.footerPartName = 'bazqux'; + + column.headerPartName = undefined; + column.footerPartName = undefined; + + expect(headerCell.getAttribute('part')).to.not.contain('foobar'); + expect(footerCell.getAttribute('part')).to.not.contain('bazqux'); + }); + }); }); diff --git a/packages/grid/test/typings/grid.types.ts b/packages/grid/test/typings/grid.types.ts index ca5e8aa7a4..bf59b3f99a 100644 --- a/packages/grid/test/typings/grid.types.ts +++ b/packages/grid/test/typings/grid.types.ts @@ -250,6 +250,8 @@ assertType(narrowedColumn.header); assertType(narrowedColumn.textAlign); assertType(narrowedColumn.path); assertType(narrowedColumn.autoWidth); +assertType(narrowedColumn.headerPartName); +assertType(narrowedColumn.footerPartName); /* GridColumnGroup */ const genericColumnGroup = document.createElement('vaadin-grid-column-group'); @@ -258,6 +260,8 @@ assertType(genericColumnGroup); const narrowedColumnGroup = genericColumnGroup as GridColumnGroup; assertType(narrowedColumnGroup); assertType>(narrowedColumnGroup); +assertType(narrowedColumnGroup.headerPartName); +assertType(narrowedColumnGroup.footerPartName); narrowedColumnGroup.headerRenderer = (root, column) => { assertType(root);