diff --git a/packages/stark-ui/src/modules/table/components/column.component.html b/packages/stark-ui/src/modules/table/components/column.component.html
index e3ec77080e..2fe6c61bd8 100644
--- a/packages/stark-ui/src/modules/table/components/column.component.html
+++ b/packages/stark-ui/src/modules/table/components/column.component.html
@@ -34,7 +34,7 @@
-
+ |
diff --git a/packages/stark-ui/src/modules/table/components/column.component.ts b/packages/stark-ui/src/modules/table/components/column.component.ts
index 05076331a9..60845d689d 100644
--- a/packages/stark-ui/src/modules/table/components/column.component.ts
+++ b/packages/stark-ui/src/modules/table/components/column.component.ts
@@ -21,6 +21,7 @@ import { distinctUntilChanged } from "rxjs/operators";
import isEqual from "lodash-es/isEqual";
import get from "lodash-es/get";
import {
+ StarkColumnCellClickedOutput,
StarkColumnFilterChangedOutput,
StarkColumnSortChangedOutput,
StarkTableColumnFilter,
@@ -184,6 +185,12 @@ export class StarkTableColumnComponent extends AbstractStarkUiComponent implemen
@Input()
public stickyEnd = false;
+ /**
+ * Output that will emit a StarkColumnCellClickedOutput whenever a cell in the column is clicked
+ */
+ @Output()
+ public readonly cellClicked = new EventEmitter();
+
/**
* Output that will emit a specific column whenever its filter value has changed
*/
@@ -264,6 +271,23 @@ export class StarkTableColumnComponent extends AbstractStarkUiComponent implemen
return rawValue !== null ? rawValue : undefined;
}
+ /**
+ * Called whenever a cell of the column is clicked
+ * @param $event - The handled event
+ * @param row - The row item
+ */
+ public onCellClick($event: Event, row: object): void {
+ if (this.cellClicked.observers.length > 0) {
+ $event.stopPropagation();
+
+ this.cellClicked.emit({
+ value: this.getRawValue(row),
+ row: row,
+ columnName: this.name
+ });
+ }
+ }
+
/**
* Get the final displayed value of the column
* @param row - The row item
diff --git a/packages/stark-ui/src/modules/table/components/table.component.spec.ts b/packages/stark-ui/src/modules/table/components/table.component.spec.ts
index d3f18305a6..55b2531274 100644
--- a/packages/stark-ui/src/modules/table/components/table.component.spec.ts
+++ b/packages/stark-ui/src/modules/table/components/table.component.spec.ts
@@ -97,6 +97,12 @@ describe("TableComponent", () => {
element.dispatchEvent(clickEvent);
};
+ const DUMMY_DATA: object[] = [
+ { id: 1, description: "dummy 1" },
+ { id: 2, description: "dummy 2" },
+ { id: 3, description: "dummy 3" }
+ ];
+
const getColumnSelector = (columnName: string): string => `.stark-table th.mat-column-${columnName} div div`;
const columnSelectSelector = "cdk-column-select";
const rowSelector = "table tbody tr";
@@ -1270,11 +1276,6 @@ describe("TableComponent", () => {
});
describe("setStyling", () => {
- const dummyData: object[] = [
- { id: 1, description: "dummy 1" },
- { id: 2, description: "dummy 2" },
- { id: 3, description: "dummy 3" }
- ];
const returnEvenAndOdd: (row: object, index: number) => string = (_row: object, index: number): string =>
(index + 1) % 2 === 0 ? "even" : "odd"; // offset index with 1
@@ -1284,7 +1285,7 @@ describe("TableComponent", () => {
{ name: "id", cellClassName: (value: any): string => (value === 1 ? "one" : "") },
{ name: "description", cellClassName: "description-body-cell", headerClassName: "description-header-cell" }
];
- hostComponent.dummyData = dummyData;
+ hostComponent.dummyData = DUMMY_DATA;
hostFixture.detectChanges(); // trigger data binding
component.ngAfterViewInit();
@@ -1327,19 +1328,52 @@ describe("TableComponent", () => {
});
});
- describe("rowClick", () => {
- const dummyData: object[] = [
- { id: 1, description: "dummy 1" },
- { id: 2, description: "dummy 2" },
- {
- id: 3,
- description: "dummy 3"
- }
- ];
+ describe("cellClick", () => {
+ const onClickCallbackSpy = createSpy("onClickCallback");
+
+ beforeEach(() => {
+ hostComponent.columnProperties = [{ name: "id" }, { name: "description", onClickCallback: onClickCallbackSpy }];
+ hostComponent.dummyData = DUMMY_DATA;
+ hostComponent.rowClickHandler = createSpy("rowClickHandlerSpy", () => undefined); // add empty function so spy can find it
+ onClickCallbackSpy.calls.reset();
+ (hostComponent.rowClickHandler).calls.reset();
+
+ hostFixture.detectChanges(); // trigger data binding
+ component.ngAfterViewInit();
+ });
+
+ it("should trigger 'onClickCallback' property when click on the cell and should not emit on 'rowClicked' when 'onClickCallback' is defined",() => {
+ const descriptionColumnElement = hostFixture.nativeElement.querySelector(
+ "table tbody tr td.mat-column-description"
+ );
+ expect(descriptionColumnElement).not.toBeNull();
+
+ // click on the cell
+ triggerClick(descriptionColumnElement);
+
+ // We expect "2" due to the check "columnProperties.onClickCallback instanceof Function" in table.component.ts
+ expect(onClickCallbackSpy).toHaveBeenCalledTimes(2);
+ expect(onClickCallbackSpy).toHaveBeenCalledWith(DUMMY_DATA[0]["description"], DUMMY_DATA[0], "description");
+ expect(hostComponent.rowClickHandler).not.toHaveBeenCalled();
+ });
+
+ it("should not trigger 'onClickCallback' property when click on the cell but should emit on 'rowClicked' when 'onClickCallback' is not defined", () => {
+ const idColumnElement = hostFixture.nativeElement.querySelector(
+ "table tbody tr td.mat-column-id"
+ );
+ expect(idColumnElement).not.toBeNull();
+
+ // click on the cell
+ triggerClick(idColumnElement);
+ expect(hostComponent.rowClickHandler).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe("rowClick", () => {
beforeEach(() => {
hostComponent.columnProperties = [{ name: "id" }, { name: "description" }];
- hostComponent.dummyData = dummyData;
+ hostComponent.dummyData = DUMMY_DATA;
hostFixture.detectChanges(); // trigger data binding
component.ngAfterViewInit();
@@ -1363,23 +1397,17 @@ describe("TableComponent", () => {
// listener should be called with the data of the first row
expect(hostComponent.rowClickHandler).toHaveBeenCalled();
- expect(hostComponent.rowClickHandler).toHaveBeenCalledWith(dummyData[0]);
+ expect(hostComponent.rowClickHandler).toHaveBeenCalledWith(DUMMY_DATA[0]);
// the row should not have been selected
- expect(component.selection.isSelected(dummyData[0])).toBe(false);
+ expect(component.selection.isSelected(DUMMY_DATA[0])).toBe(false);
});
});
describe("selection", () => {
- const dummyData: object[] = [
- { id: 1, description: "dummy 1" },
- { id: 2, description: "dummy 2" },
- { id: 3, description: "dummy 3" }
- ];
-
beforeEach(() => {
hostComponent.columnProperties = [{ name: "id" }, { name: "description" }];
- hostComponent.dummyData = dummyData;
+ hostComponent.dummyData = DUMMY_DATA;
hostComponent.rowsSelectable = true;
hostFixture.detectChanges(); // trigger data binding
@@ -1401,8 +1429,8 @@ describe("TableComponent", () => {
hostFixture.detectChanges();
expect(rowElement.classList).toContain("selected");
- expect(component.selectChanged.emit).toHaveBeenCalledWith([dummyData[0]]);
- expect(component.selection.isSelected(dummyData[0])).toBe(true);
+ expect(component.selectChanged.emit).toHaveBeenCalledWith([DUMMY_DATA[0]]);
+ expect(component.selection.isSelected(DUMMY_DATA[0])).toBe(true);
});
it("should select the right rows in the template when selecting them through host 'selection' object", () => {
@@ -1417,10 +1445,10 @@ describe("TableComponent", () => {
expect(rowsElements[1].classList).not.toContain("selected");
expect(rowsElements[2].classList).not.toContain("selected");
- hostComponent.selection.select(dummyData[1]);
+ hostComponent.selection.select(DUMMY_DATA[1]);
hostFixture.detectChanges();
- expect(component.selection.selected).toEqual([dummyData[1]]);
+ expect(component.selection.selected).toEqual([DUMMY_DATA[1]]);
expect(rowsElements[0].classList).not.toContain("selected");
expect(rowsElements[1].classList).toContain("selected");
expect(rowsElements[2].classList).not.toContain("selected");
@@ -1432,7 +1460,7 @@ describe("TableComponent", () => {
beforeEach(() => {
hostComponent.columnProperties = [{ name: "id" }, { name: "description" }];
- hostComponent.dummyData = dummyData;
+ hostComponent.dummyData = DUMMY_DATA;
hostComponent.selection = new SelectionModel |