Skip to content

Commit

Permalink
feat(stark-ui): add custom styling functionality to stark table compo…
Browse files Browse the repository at this point in the history
…nent

  - added properties to stark-table component to allow for custom styling
  - added tests for new functionality
  - added demo component demonstrating new functionality
  - removed className property from `StarkTableColumnProperties`
  - moved cellClassNameFn property to cellClassName in `StarkTableColumnProperties`

ISSUES CLOSED: NationalBankBelgium#523
  • Loading branch information
carlo-nomes committed Nov 16, 2018
1 parent fbabeef commit 166e94e
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@ import { StarkTableColumnPriority } from "./column-priority.intf";
* Definition of a column in the Stark Table
*/
export interface StarkTableColumnProperties {
/**
* Class(es) to be set to every cell of the column.
*/
cellClassName?: string;

/**
* Function that returns class(es) to be set to an specific cell. It can be used to set different classes
* depending on the row, value and or columnName. This function is called with 3 parameters:
* @param value - The value of the cell
* @param row - The row object that contains the cell
* @param columnName - The column that the cell belongs to
*
* This could also be a static string with class(es)
*/
cellClassNameFn?: (value: any, row?: any, columnName?: string) => string;
cellClassName?: ((value: any, row?: any, columnName?: string) => string) | string;

/**
* Function that returns a formatted value (string) to be set in the cell. It can be used to set different formats
Expand All @@ -27,13 +24,6 @@ export interface StarkTableColumnProperties {
*/
cellFormatter?: (value: any, row?: any, columnName?: string) => string;

/**
* Class(es) to be set to the colgroup>col element of the column.
* The CSS linked to the style can only be applied to 'border', 'background', 'width' and 'visibility' properties.
* See http://www.w3.org/TR/CSS2/tables.html#columns
*/
className?: string;

/**
* Function that returns
* 1 : if obj1 > obj2
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<ng-container matColumnDef>
<!-- custom header that supports multi-column sorting -->
<!-- TODO: implement a MultiSort directive based on the Angular Material's MatSort once this is solved: https://github.com/angular/material2/issues/7226 -->
<th mat-header-cell *matHeaderCellDef [ngClass]="getHeaderClassName()">
<th mat-header-cell *matHeaderCellDef [ngClass]="getHeaderClassNames()">
<div class="header-cell-content">
<div [ngSwitch]="sortDirection" class="sort-header" (click)="onSortChange()">
<span>{{ getHeaderLabel() }}</span>
Expand Down Expand Up @@ -31,7 +31,7 @@
</th>
<!-- the column template defined by the user will be displayed here -->
<!-- and it will receive the right context containing the displayedValue and the row data-->
<td mat-cell *matCellDef="let rowItem" [ngClass]="getCellClassName(rowItem)">
<td mat-cell *matCellDef="let rowItem" [ngClass]="getCellClassNames(rowItem)">
<ng-container
*ngTemplateOutlet="columnTemplate; context:{ $implicit: { rowData: rowItem, displayedValue: getDisplayedValue(rowItem) } }"></ng-container>
</td>
Expand Down
31 changes: 17 additions & 14 deletions packages/stark-ui/src/modules/table/components/column.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,18 @@ export class StarkTableColumnComponent extends AbstractStarkUiComponent {
@Input()
public sortPriority: number;

@Input()
public className?: string;

/**
* A function to generate classNames for cells based on the value, its row and the name of the column.
* The classNames for the colgroup > col
*/
@Input()
public cellClassNameFn?: (value: any, row?: any, columnName?: string) => string;
public className?: string;

/**
* A static className that will be applied to all cells.
* A function to generate classNames for cells based on the value, its row and the name of the column.
* Or a static string with the classNames.
*/
@Input()
public cellClassName?: string;
public cellClassName?: ((value: any, row?: any, columnName?: string) => string) | string;

/**
* A static className for the header
Expand Down Expand Up @@ -252,19 +250,24 @@ export class StarkTableColumnComponent extends AbstractStarkUiComponent {
* @param row - The data object of the row the cell is in.
* @returns The classes for the cell.
*/
public getCellClassName(row: any): string {
const value: any | undefined = this.getRawValue(row);
const classNameFnResult: string =
(this.cellClassNameFn && typeof this.cellClassNameFn === "function" && this.cellClassNameFn(value, row, this.name)) || "";
return `${classNameFnResult} ${this.cellClassName || ""}`;
public getCellClassNames(row: any): string {
if (!this.cellClassName) {
return "";
}
if (typeof this.cellClassName === "string") {
return this.cellClassName;
}

const value: any = this.getRawValue(row);
return this.cellClassName(value, row, this.name);
}

/**
* Get the classes for a header
* @returns The classes for the header
*/
public getHeaderClassName(): string {
const classes: Array<string> = [];
public getHeaderClassNames(): string {
const classes: string[] = [];

if (this.sortable) {
classes.push("sortable");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
</td>
</ng-container>

<colgroup>
<col *ngFor="let col of columnProperties; trackBy: trackColumnFn" [class]="col.className">
</colgroup>
<stark-table-column *ngFor="let col of columnProperties; trackBy: trackColumnFn"
[name]="col.name"
[headerLabel]="col.label"
Expand All @@ -61,8 +64,6 @@
[filterValue]="getColumnFilterValue(col.name)"
[compareFn]="col.compareFn"
[cellFormatter]="col.cellFormatter"
[className]="col.className"
[cellClassNameFn]="col.cellClassNameFn"
[cellClassName]="col.cellClassName"
[headerClassName]="col.headerClassName">
<ng-template let-context>
Expand All @@ -82,7 +83,7 @@
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: isFixedHeaderEnabled"></tr>
<tr mat-row
*matRowDef="let row; columns: displayedColumns; let i = index;"
[ngClass]="getRowClass(row, i)">
[ngClass]="getRowClasses(row, i)">
</tr>
</table>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -899,37 +899,34 @@ describe("TableComponent", () => {
});

describe("setStyling", () => {
const dummyData: Array<any> = [
{ id: 1, description: "dummy 1" },
{ id: 2, description: "dummy 2" },
{ id: 3, description: "dummy 3" }
];
const dummyData: any[] = [{ id: 1, description: "dummy 1" }, { id: 2, description: "dummy 2" }, { id: 3, description: "dummy 3" }];
const returnEvenAndOdd: (row: any, index: number) => string = (_row: any, index: number): string =>
index % 2 === 0 ? "even" : "odd";
const staticCellClass: string = "staticCellClass";
(index + 1) % 2 === 0 ? "even" : "odd"; // offset index with 1

beforeEach(() => {
hostComponent.rowClassNameFn = returnEvenAndOdd;
hostComponent.columnProperties = [
{ name: "id", headerClassName: "id-header-cell", cellClassNameFn: (value: any) => (value === 1 ? "one" : "") },
{ name: "description", cellClassName: staticCellClass }
{ name: "id", cellClassName: (value: any) => console.log(value) || (value === 1 ? "one" : "") },
{ name: "description", headerClassName: "description-header-cell" }
];
hostComponent.dummyData = dummyData;

hostFixture.detectChanges(); // trigger data binding
component.ngAfterViewInit();
});

it("second row should have class 'even'", () => {
const tableElement: HTMLElement = hostFixture.nativeElement;
const secondRow: HTMLElement | null = tableElement.querySelectorAll("tr").item(1);
expect(secondRow && secondRow.classList).toContain("even");
});
describe("setRowClass", () => {
it("first row should have class 'odd", () => {
const tableElement: HTMLElement = hostFixture.nativeElement;
const firstRow: HTMLElement | null = tableElement.querySelectorAll<HTMLElement>("tbody tr").item(0);
expect(firstRow && firstRow.classList).toContain("odd");
});

it(`cell description should have class 'staticCellClass'`, () => {
const tableElement: HTMLElement = hostFixture.nativeElement;
const descriptionCell: HTMLElement | null = tableElement.querySelector("tr td:nth-child(2)"); // select the description cells
expect(descriptionCell && descriptionCell.classList).toContain(staticCellClass);
it("second row should have class 'even'", () => {
const tableElement: HTMLElement = hostFixture.nativeElement;
const secondRow: HTMLElement | null = tableElement.querySelectorAll<HTMLElement>("tbody tr").item(1);
expect(secondRow && secondRow.classList).toContain("even");
});
});

it("cell id should have class 'one'", () => {
Expand All @@ -938,10 +935,10 @@ describe("TableComponent", () => {
expect(descriptionCell && descriptionCell.classList).toContain("one");
});

it("id header cell should have class 'id-header-cell'", () => {
it("description header cell should have class 'description-header-cell'", () => {
const tableElement: HTMLElement = hostFixture.nativeElement;
const descriptionCell: HTMLElement | null = tableElement.querySelector("thead th:nth-child(1)"); // select the id cells
expect(descriptionCell && descriptionCell.classList).toContain("id-header-cell");
const descriptionCell: HTMLElement | null = tableElement.querySelector("thead th:nth-child(2)"); // select the id cells
expect(descriptionCell && descriptionCell.classList).toContain("description-header-cell");
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export class StarkTableComponent extends AbstractStarkUiComponent implements OnI
public tableRowsActionBarConfig: StarkActionBarConfig;

/**
* function to generate a classNames for rows
* Function to generate classNames for rows
*/
@Input()
public rowClassNameFn?: (row: any, index: number) => string;
Expand Down Expand Up @@ -730,8 +730,8 @@ export class StarkTableComponent extends AbstractStarkUiComponent implements OnI
* @param index - The index of the row.
* @returns The className generated by the rowClassNameFn function
*/
public getRowClass(row: any, index: number): string {
return this.rowClassNameFn && typeof this.rowClassNameFn === "function" ? this.rowClassNameFn(row, index) : "";
public getRowClasses(row: any, index: number): string {
return typeof this.rowClassNameFn === "function" ? this.rowClassNameFn(row, index) : "";
}

/**
Expand Down
30 changes: 7 additions & 23 deletions showcase/src/app/demo/table/demo-table.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,18 @@
background-color: #d1e1ff;
}

td {
&.danger {
color: #7c002c;
}
&.warning {
color: #ff9800;
}
&.success {
color: #3c9f40;
}
.danger {
color: #7c002c;
}

.even td {
background-color: #d1e1ff;
.warning {
color: #ff9800;
}

td {
&.danger {
color: #7c002c;
}
&.warning {
color: #ff9800;
}
&.success {
color: #3c9f40;
}
.success {
color: #3c9f40;
}

th.bold {
.bold {
font-weight: bold;
}
4 changes: 2 additions & 2 deletions showcase/src/app/demo/table/demo-table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class DemoTableComponent implements OnInit {
return 0;
};

public getRowClassName = (_row: any, index: number): Object => (index % 2 === 0 ? "even" : "odd");
public getRowClassName = (_row: any, index: number): string => (index % 2 === 0 ? "even" : "odd");

public getTitleCellClassName = (title: { value: number }): string =>
title.value < 5 ? "danger" : title.value < 9 ? "warning" : "success";
Expand Down Expand Up @@ -112,7 +112,7 @@ export class DemoTableComponent implements OnInit {
isSortable: true,
isFilterable: true,
compareFn: this.compareTitle,
cellClassNameFn: this.getTitleCellClassName
cellClassName: this.getTitleCellClassName
},
{
name: "description",
Expand Down
22 changes: 11 additions & 11 deletions showcase/src/assets/examples/table/with-custom-styling.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
background-color: #d1e1ff;
}

td {
&.danger {
color: #7c002c;
}
&.warning {
color: #ff9800;
}
&.success {
color: #3c9f40;
}
.danger {
color: #7c002c;
}

th.bold {
.warning {
color: #ff9800;
}

.success {
color: #3c9f40;
}

.bold {
font-weight: bold;
}
2 changes: 1 addition & 1 deletion showcase/src/assets/examples/table/with-custom-styling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class DemoTableComponent implements OnInit {
},
isSortable: true,
isFilterable: true,
cellClassNameFn: this.getTitleCellClassName
cellClassName: this.getTitleCellClassName
},
{
name: "description",
Expand Down
2 changes: 1 addition & 1 deletion showcase/src/assets/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
"WITH_ALTERNATIVE_ACTION_BAR": "Table avec Action Bar alternative",
"WITH_FIXED_HEADER": "Table avec un en-tête fixe",
"WITH_TRANSCLUDED_ACTION_BAR": "Table avec Action Bar 'transcluded'",
"WITH_CUSTOM_STYLING": "Table avec mis en page personnalisé",
"WITH_CUSTOM_STYLING": "Table avec mise en page personnalisé",
"TITLE": "Stark table"
},
"TOAST": {
Expand Down

0 comments on commit 166e94e

Please sign in to comment.