Skip to content

Commit

Permalink
fix(stark-ui): table - Add support to show row index
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #1283
  • Loading branch information
SuperITMan committed May 21, 2019
1 parent 4ddb7c5 commit 9781a44
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@
</td>
</ng-container>

<ng-container matColumnDef="rowIndex">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let row">{{ getRowIndex(row) }}</td>
</ng-container>

<stark-table-column
*ngFor="let col of columnProperties; trackBy: trackColumnFn"
[name]="col.name"
Expand Down
161 changes: 143 additions & 18 deletions packages/stark-ui/src/modules/table/components/table.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { StarkTableComponent } from "./table.component";
import { StarkTableColumnComponent } from "./column.component";
import { StarkPaginationComponent } from "../../pagination/components";
import { StarkTableColumnFilter, StarkTableColumnProperties, StarkTableFilter, StarkTableRowActions } from "../entities";
import find from "lodash-es/find";
import Spy = jasmine.Spy;
import createSpy = jasmine.createSpy;

Expand All @@ -36,6 +37,7 @@ import createSpy = jasmine.createSpy;
[multiSort]="multiSort"
[rowsSelectable]="rowsSelectable"
[multiSelect]="multiSelect"
[showRowIndex]="showRowIndex"
[orderProperties]="orderProperties"
[tableRowActions]="tableRowActions"
[rowClassNameFn]="rowClassNameFn"
Expand All @@ -54,6 +56,7 @@ class TestHostComponent {
public rowsSelectable?: boolean;
public multiSelect?: string;
public multiSort?: string;
public showRowIndex?: boolean;
public tableRowActions?: StarkTableRowActions;
public tableFilter?: StarkTableFilter;
public orderProperties?: string[];
Expand Down Expand Up @@ -149,13 +152,16 @@ describe("TableComponent", () => {
expect(component.filter).toBeDefined(); // the default filter is set
expect(component.fixedHeader).toBe(hostComponent.fixedHeader);
expect(component.multiSelect).toBe(hostComponent.multiSelect);
expect(component.showRowIndex).toBe(false);
expect(component.multiSort).toBe(hostComponent.multiSort);
expect(component.orderProperties).toBe(hostComponent.orderProperties);
expect(component.tableRowActions).toBe(<any>hostComponent.tableRowActions);
});
});

describe("on change", () => {
const tableThSelector = ".stark-table thead tr th";

it("should make a copy of 'data' in 'dataSource' when 'data' changes to keep 'data' immutable", () => {
const dummyData = [{ name: "test-data" }];
hostComponent.dummyData = dummyData;
Expand All @@ -164,7 +170,7 @@ describe("TableComponent", () => {
expect(component.dataSource.data).toEqual(dummyData);
expect(component.dataSource.data).not.toBe(component.data);
});

it("should trigger resetFilterValueOnDataChange and sortData methods when data changes", () => {
spyOn(component, "resetFilterValueOnDataChange");
spyOn(component, "sortData");
Expand Down Expand Up @@ -220,20 +226,63 @@ describe("TableComponent", () => {
expect(component.isMultiSortEnabled).toBe(false);
});

it("should assign right value to isMultiSelectEnabled when multiSelect changes and adapt displayedColumns", () => {
spyOn(component.displayedColumns, "unshift");
it("should assign right value to isMultiSelectEnabled when multiSelect changes and rowsSelectable is enabled", () => {
hostComponent.rowsSelectable = true;
hostComponent.multiSelect = "true";
hostFixture.detectChanges();
expect(component.isMultiSelectEnabled).toBe(true);

hostComponent.multiSelect = "false";
hostFixture.detectChanges();
expect(component.isMultiSelectEnabled).toBe(false);
});

it("should assign right value to display/hide 'select' column when rowsSelectable changes", () => {
spyOn(component.displayedColumns, "unshift").and.callThrough();
hostComponent.rowsSelectable = true;
hostFixture.detectChanges();

expect(component.displayedColumns.unshift).toHaveBeenCalledTimes(1);
expect(component.displayedColumns.unshift).toHaveBeenCalledWith("select");
let rowThElements = <NodeListOf<HTMLElement>>hostFixture.nativeElement.querySelectorAll(tableThSelector);
expect(rowThElements.length).toBeGreaterThan(0);
let selectThElement = find(rowThElements, (thElement: HTMLElement) => thElement.className.indexOf("cdk-column-select") > -1);
expect(selectThElement).toBeDefined();

(<Spy>component.displayedColumns.unshift).calls.reset();
hostComponent.multiSelect = "false";
hostComponent.rowsSelectable = false;
hostFixture.detectChanges();
expect(component.isMultiSelectEnabled).toBe(false);
expect(component.displayedColumns.unshift).not.toHaveBeenCalled();
rowThElements = <NodeListOf<HTMLElement>>hostFixture.nativeElement.querySelectorAll(tableThSelector);
expect(rowThElements.length).toBeGreaterThanOrEqual(0);
selectThElement = find(rowThElements, (thElement: HTMLElement) => thElement.className.indexOf("cdk-column-select") > -1);
expect(selectThElement).toBeUndefined();
});

it("should assign right value to _showRowIndex when showRowIndex changes and adapt displayedColumns", () => {
spyOn(component.displayedColumns, "unshift").and.callThrough();
hostComponent.showRowIndex = true;
hostFixture.detectChanges();
expect(component._showRowIndex).toBe(true);
expect(component.displayedColumns.unshift).toHaveBeenCalledTimes(1);
expect(component.displayedColumns.unshift).toHaveBeenCalledWith("rowIndex");
let rowThElements = <NodeListOf<HTMLElement>>hostFixture.nativeElement.querySelectorAll(tableThSelector);
expect(rowThElements.length).toBeGreaterThan(0);
let rowIndexThElement = find(
rowThElements,
(thElement: HTMLElement) => thElement.className.indexOf("cdk-column-rowIndex") > -1
);
expect(rowIndexThElement).toBeDefined();

(<Spy>component.displayedColumns.unshift).calls.reset();
hostComponent.showRowIndex = false;
hostFixture.detectChanges();
expect(component._showRowIndex).toBe(false);
expect(component.displayedColumns.unshift).not.toHaveBeenCalled();
rowThElements = <NodeListOf<HTMLElement>>hostFixture.nativeElement.querySelectorAll(tableThSelector);
expect(rowThElements.length).toBeGreaterThanOrEqual(0);
rowIndexThElement = find(rowThElements, (thElement: HTMLElement) => thElement.className.indexOf("cdk-column-rowIndex") > -1);
expect(rowIndexThElement).toBeUndefined();
});

it("should assign the right value to filter", () => {
Expand Down Expand Up @@ -274,7 +323,16 @@ describe("TableComponent", () => {

component.sortData();

expect(component.dataSource.data).toEqual([{ a: 1 }, { a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 10 }, { a: 20 }]);
expect(component.dataSource.data).toEqual([
{ a: 1 },
{ a: 1 },
{ a: 2 },
{ a: 3 },
{ a: 4 },
{ a: 5 },
{ a: 10 },
{ a: 20 }
]);
});

it("should sort data descending", () => {
Expand All @@ -285,7 +343,16 @@ describe("TableComponent", () => {

component.sortData();

expect(component.dataSource.data).toEqual([{ a: 20 }, { a: 10 }, { a: 5 }, { a: 4 }, { a: 3 }, { a: 2 }, { a: 1 }, { a: 1 }]);
expect(component.dataSource.data).toEqual([
{ a: 20 },
{ a: 10 },
{ a: 5 },
{ a: 4 },
{ a: 3 },
{ a: 2 },
{ a: 1 },
{ a: 1 }
]);
});

it("should sort data descending column A then ascending column B", () => {
Expand Down Expand Up @@ -371,40 +438,85 @@ describe("TableComponent", () => {

component.sortData();

expect(component.dataSource.data).toEqual([{ a: 1 }, { a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 10 }, { a: 20 }]);
expect(component.dataSource.data).toEqual([
{ a: 1 },
{ a: 1 },
{ a: 2 },
{ a: 3 },
{ a: 4 },
{ a: 5 },
{ a: 10 },
{ a: 20 }
]);
expect(hostComponent.columnProperties[0].compareFn).toHaveBeenCalled();
// Due to browsers, we cannot predict exactly the number of calls. On IE, it is 9 times, on Chrome it can be 7, 8 or 14 times depending on the version
// Due to browsers, we cannot predict exactly the number of calls. On IE, it is 9 times, on Chrome it can be 7, 8 or 14 times depending on the version
expect((<Spy>hostComponent.columnProperties[0].compareFn).calls.count()).toBeGreaterThanOrEqual(7);
expect((<Spy>hostComponent.columnProperties[0].compareFn).calls.count()).toBeLessThanOrEqual(14);
});

it("should sort data when click on the column", () => {
expect(component.dataSource.data).toEqual([{ a: 1 }, { a: 1 }, { a: 3 }, { a: 2 }, { a: 4 }, { a: 5 }, { a: 10 }, { a: 20 }]);

expect(component.dataSource.data).toEqual([
{ a: 1 },
{ a: 1 },
{ a: 3 },
{ a: 2 },
{ a: 4 },
{ a: 5 },
{ a: 10 },
{ a: 20 }
]);

const column: HTMLElement = hostFixture.debugElement.nativeElement.querySelector(getColumnSelector("a"));
column.click();
hostFixture.detectChanges();
expect(component.dataSource.data).toEqual([{ a: 1 }, { a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 10 }, { a: 20 }]);
expect(component.dataSource.data).toEqual([
{ a: 1 },
{ a: 1 },
{ a: 2 },
{ a: 3 },
{ a: 4 },
{ a: 5 },
{ a: 10 },
{ a: 20 }
]);

column.click();
hostFixture.detectChanges();
expect(component.dataSource.data).toEqual([{ a: 20 }, { a: 10 }, { a: 5 }, { a: 4 }, { a: 3 }, { a: 2 }, { a: 1 }, { a: 1 }]);
expect(component.dataSource.data).toEqual([
{ a: 20 },
{ a: 10 },
{ a: 5 },
{ a: 4 },
{ a: 3 },
{ a: 2 },
{ a: 1 },
{ a: 1 }
]);

column.click();
hostFixture.detectChanges();
expect(component.dataSource.data).toEqual([{ a: 1 }, { a: 1 }, { a: 3 }, { a: 2 }, { a: 4 }, { a: 5 }, { a: 10 }, { a: 20 }]);
expect(component.dataSource.data).toEqual([
{ a: 1 },
{ a: 1 },
{ a: 3 },
{ a: 2 },
{ a: 4 },
{ a: 5 },
{ a: 10 },
{ a: 20 }
]);
});

it("should sort data when click on different columns", () => {
hostComponent.dummyData = [{ a: 2, b: 3, c: 1 }, { a: 1, b: 2, c: 3 }, { a: 3, b: 1, c: 2 }];
hostComponent.columnProperties = [{ name: "a" }, { name: "b" }, { name: "c" }];
hostFixture.detectChanges();
expect(component.dataSource.data).toEqual(hostComponent.dummyData);

const columnA: HTMLElement = hostFixture.debugElement.nativeElement.querySelector(getColumnSelector("a"));
const columnB: HTMLElement = hostFixture.debugElement.nativeElement.querySelector(getColumnSelector("b"));
const columnC: HTMLElement = hostFixture.debugElement.nativeElement.querySelector(getColumnSelector("c"));

columnA.click();
expect(component.dataSource.data).toEqual([{ a: 1, b: 2, c: 3 }, { a: 2, b: 3, c: 1 }, { a: 3, b: 1, c: 2 }]);
columnA.click();
Expand All @@ -414,7 +526,7 @@ describe("TableComponent", () => {
expect(component.dataSource.data).toEqual([{ a: 3, b: 1, c: 2 }, { a: 1, b: 2, c: 3 }, { a: 2, b: 3, c: 1 }]);
columnB.click();
expect(component.dataSource.data).toEqual([{ a: 2, b: 3, c: 1 }, { a: 1, b: 2, c: 3 }, { a: 3, b: 1, c: 2 }]);

columnC.click();
expect(component.dataSource.data).toEqual([{ a: 2, b: 3, c: 1 }, { a: 3, b: 1, c: 2 }, { a: 1, b: 2, c: 3 }]);
columnC.click();
Expand Down Expand Up @@ -574,7 +686,7 @@ describe("TableComponent", () => {
{ a: { b: 7 } }
]);
expect(hostComponent.columnProperties[0].compareFn).toHaveBeenCalled();
// Due to browsers, we cannot predict exactly the number of calls. On IE, it is 9 times, on Chrome it can be 7, 8 or 14 times depending on the version
// Due to browsers, we cannot predict exactly the number of calls. On IE, it is 9 times, on Chrome it can be 7, 8 or 14 times depending on the version
expect((<Spy>hostComponent.columnProperties[0].compareFn).calls.count()).toBeGreaterThanOrEqual(7);
expect((<Spy>hostComponent.columnProperties[0].compareFn).calls.count()).toBeLessThanOrEqual(14);
});
Expand Down Expand Up @@ -972,6 +1084,19 @@ describe("TableComponent", () => {
});
});

describe("getRowIndex", () => {
it("should return the right index for every row", () => {
for (let i = 0; i < component.dataSource.data.length; i++) {
expect(component.getRowIndex(component.dataSource.data[i])).toBe(i + 1);
}
});

it("should return 'undefined' if dataSource is not initialized yet", () => {
component.dataSource = <any>undefined;
expect(component.getRowIndex({ name: "dummy-row-data" })).toBeUndefined();
});
});

describe("resetFilterValueOnDataChange", () => {
const dummyGlobalFilterValue = "dummy global filter value";
const dummyColumnFilterValue = "dummy column filter value";
Expand Down
41 changes: 41 additions & 0 deletions packages/stark-ui/src/modules/table/components/table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { MatDialog, MatDialogRef } from "@angular/material/dialog";
import { MatColumnDef, MatTable, MatTableDataSource } from "@angular/material/table";
import { SelectionChange, SelectionModel } from "@angular/cdk/collections";
import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { STARK_LOGGING_SERVICE, StarkLoggingService } from "@nationalbankbelgium/stark-core";
import { Subscription } from "rxjs";

Expand Down Expand Up @@ -224,6 +225,34 @@ export class StarkTableComponent extends AbstractStarkUiComponent implements OnI
@Input()
public rowClassNameFn?: (row: object, index: number) => string;

/**
* Determine if the row index must be present or not.
* Default: false
*/
@Input()
public get showRowIndex(): boolean {
return this._showRowIndex;
}

public set showRowIndex(showRowIndex: boolean) {
this._showRowIndex = coerceBooleanProperty(showRowIndex);

if (this._showRowIndex) {
if (!this.displayedColumns.includes("rowIndex")) {
this.displayedColumns.unshift("rowIndex");
}
} else {
const i: number = this.displayedColumns.indexOf("rowIndex");
this.displayedColumns.splice(i);
}
}

/**
* @ignore
* @internal
*/
public _showRowIndex = false;

/**
* Output event emitter that will emit the latest filter value whenever it changes.
*/
Expand Down Expand Up @@ -939,6 +968,18 @@ export class StarkTableComponent extends AbstractStarkUiComponent implements OnI
}
}

/**
* Get the row index, based on its position in dataSource.data
* @param row - Row to get index
*/
public getRowIndex(row: any): number | undefined {
if (this.dataSource && this.dataSource.data) {
return this.dataSource.data.indexOf(row) + 1;
}

return undefined;
}

/**
* Toggles the visibility of a column
* @param item - the item containing the name of the column
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[orderProperties]="order"
[paginationConfig]="pagination"
[tableRowActions]="tableRowActions"
showRowIndex
multiSort
(rowClicked)="handleRowClicked($event)"
>
Expand Down
1 change: 1 addition & 0 deletions showcase/src/assets/examples/table/regular/table.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[orderProperties]="order"
[paginationConfig]="pagination"
[tableRowActions]="tableRowActions"
showRowIndex
multiSort
(rowClicked)="handleRowClicked($event)"
>
Expand Down

0 comments on commit 9781a44

Please sign in to comment.