From 1748397d8338e49671d1b652b1a0a2ec3544a974 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 2 Aug 2017 15:36:30 -0700 Subject: [PATCH] fix(table): column class names should be css friendly (#6173) * fix(table): column class names should be css friendly * rename function * add to docs, replace with -, make var * fix test --- guides/cdk-table.md | 11 +++++++++++ src/cdk/table/cell.ts | 19 ++++++++++++++++--- src/cdk/table/table.spec.ts | 32 ++++++++++++++++++++++++++++++++ src/lib/table/cell.ts | 4 ++-- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/guides/cdk-table.md b/guides/cdk-table.md index 61c2c55eecc..08a7027b3bf 100644 --- a/guides/cdk-table.md +++ b/guides/cdk-table.md @@ -107,6 +107,17 @@ Event and property bindings can be added directly to the row element. ``` +##### Styling columns + +Each header and row cell will be provided a CSS class that includes its column. For example, +cells that are displayed in the column `name` will be given the class `cdk-column-name`. This allows +columns to be given styles that will match across the header and rows. + +Since columns can be given any string for its name, its possible that it cannot be directly applied +to the CSS class (e.g. `*nameColumn!`). In these cases, the special characters will be replaced by +the `-` character. For example, cells container in a column named `*nameColumn!` will be given +the class `cdk-column--nameColumn-`. + #### Connecting the table to a data source Data is provided to the table through a `DataSource`. When the table receives a data source, diff --git a/src/cdk/table/cell.ts b/src/cdk/table/cell.ts index 36f319756f0..994156fbf44 100644 --- a/src/cdk/table/cell.ts +++ b/src/cdk/table/cell.ts @@ -33,13 +33,26 @@ export class CdkHeaderCellDef { @Directive({selector: '[cdkColumnDef]'}) export class CdkColumnDef { /** Unique name for this column. */ - @Input('cdkColumnDef') name: string; + @Input('cdkColumnDef') + get name(): string { return this._name; } + set name(name: string) { + this._name = name; + this.cssClassFriendlyName = name.replace(/[^a-z0-9_-]/ig, '-'); + } + _name: string; /** @docs-private */ @ContentChild(CdkCellDef) cell: CdkCellDef; /** @docs-private */ @ContentChild(CdkHeaderCellDef) headerCell: CdkHeaderCellDef; + + /** + * Transformed version of the column name that can be used as part of a CSS classname. Excludes + * all non-alphanumeric characters and the special characters '-' and '_'. Any characters that + * do not match are replaced by the '-' character. + */ + cssClassFriendlyName: string; } /** Header cell template container that adds the right classes and role. */ @@ -52,7 +65,7 @@ export class CdkColumnDef { }) export class CdkHeaderCell { constructor(columnDef: CdkColumnDef, elementRef: ElementRef, renderer: Renderer2) { - renderer.addClass(elementRef.nativeElement, `cdk-column-${columnDef.name}`); + renderer.addClass(elementRef.nativeElement, `cdk-column-${columnDef.cssClassFriendlyName}`); } } @@ -66,6 +79,6 @@ export class CdkHeaderCell { }) export class CdkCell { constructor(columnDef: CdkColumnDef, elementRef: ElementRef, renderer: Renderer2) { - renderer.addClass(elementRef.nativeElement, `cdk-column-${columnDef.name}`); + renderer.addClass(elementRef.nativeElement, `cdk-column-${columnDef.cssClassFriendlyName}`); } } diff --git a/src/cdk/table/table.spec.ts b/src/cdk/table/table.spec.ts index 8f614bff24e..c22b28bfba3 100644 --- a/src/cdk/table/table.spec.ts +++ b/src/cdk/table/table.spec.ts @@ -29,6 +29,7 @@ describe('CdkTable', () => { RowContextCdkTableApp, DuplicateColumnDefNameCdkTableApp, MissingColumnDefCdkTableApp, + CrazyColumnNameCdkTableApp, ], }).compileComponents(); })); @@ -97,6 +98,17 @@ describe('CdkTable', () => { }); }); + it('should be able to apply class-friendly css class names for the column cells', () => { + const crazyColumnNameAppFixture = TestBed.createComponent(CrazyColumnNameCdkTableApp); + const crazyColumnNameTableElement = + crazyColumnNameAppFixture.nativeElement.querySelector('cdk-table'); + crazyColumnNameAppFixture.detectChanges(); + + // Column was named 'crazy-column-NAME-1!@#$%^-_&*()2' + expect(getHeaderCells(crazyColumnNameTableElement)[0].classList) + .toContain('cdk-column-crazy-column-NAME-1-------_----2'); + }); + it('should disconnect the data source when table is destroyed', () => { expect(dataSource.isConnected).toBe(true); @@ -682,6 +694,26 @@ class CustomRoleCdkTableApp { @ViewChild(CdkTable) table: CdkTable; } +@Component({ + template: ` + + + Column A + {{row.a}} + + + + + + ` +}) +class CrazyColumnNameCdkTableApp { + dataSource: FakeDataSource = new FakeDataSource(); + columnsToRender = ['crazy-column-NAME-1!@#$%^-_&*()2']; + + @ViewChild(CdkTable) table: CdkTable; +} + @Component({ template: ` diff --git a/src/lib/table/cell.ts b/src/lib/table/cell.ts index f2103edb102..00ea3ed066e 100644 --- a/src/lib/table/cell.ts +++ b/src/lib/table/cell.ts @@ -68,7 +68,7 @@ export class MdHeaderCell extends _MdHeaderCell { elementRef: ElementRef, renderer: Renderer2) { super(columnDef, elementRef, renderer); - renderer.addClass(elementRef.nativeElement, `mat-column-${columnDef.name}`); + renderer.addClass(elementRef.nativeElement, `mat-column-${columnDef.cssClassFriendlyName}`); } } @@ -85,6 +85,6 @@ export class MdCell extends _MdCell { elementRef: ElementRef, renderer: Renderer2) { super(columnDef, elementRef, renderer); - renderer.addClass(elementRef.nativeElement, `mat-column-${columnDef.name}`); + renderer.addClass(elementRef.nativeElement, `mat-column-${columnDef.cssClassFriendlyName}`); } }