Skip to content

Commit

Permalink
feat(platform): table not selectable and preselected rows (#9304)
Browse files Browse the repository at this point in the history
* chore(platform): table refactoring

* feat(platform): table preselected rows, disable selection for row features

* fix(platform): table refactoring

* fix(platform): table's unit tests
  • Loading branch information
platon-rov authored Feb 9, 2023
1 parent b9b27dc commit e66901b
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 34 deletions.
8 changes: 5 additions & 3 deletions libs/docs/platform/table/e2e/table.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ describe('Table component test suite', () => {

describe('Check Multi Row Selection', () => {
it('should verify checkboxes', async () => {
await checkAllCheckbox(tableMultipleRowSelectionExample);
await checkAllCheckbox(tableMultipleRowSelectionExample, true);
});
});

Expand Down Expand Up @@ -923,12 +923,14 @@ describe('Table component test suite', () => {
await click(barButton);
}

async function checkAllCheckbox(selector): Promise<void> {
async function checkAllCheckbox(selector, skipFirst = false): Promise<void> {
await scrollIntoView(selector);
await click(selector + 'fd-checkbox');
const checkboxLength = await getElementArrayLength(selector + tableRow);
for (let i = 0; i < checkboxLength; i++) {
await expect(await getAttributeByName(selector + tableRow, 'aria-selected', i)).toBe('true');
await expect(await getAttributeByName(selector + tableRow, 'aria-selected', i)).toBe(
skipFirst && i === 0 ? 'false' : 'true'
);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<fdp-table
[dataSource]="source"
selectionMode="multiple"
selectableKey="selectable"
selectedKey="selected"
emptyTableMessage="No data found"
(rowSelectionChange)="onRowSelectionChange($event)"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export interface ExampleItem {
statusColor?: string;
date: FdDate;
verified: boolean;
selectable?: boolean;
selected?: boolean;
}

/**
Expand Down Expand Up @@ -93,7 +95,8 @@ const ITEMS: ExampleItem[] = [
status: 'Stocked on demand',
statusColor: 'informative',
date: new FdDate(2020, 1, 7),
verified: true
verified: true,
selectable: false
},
{
name: 'Astro Laptop 1516',
Expand All @@ -105,7 +108,8 @@ const ITEMS: ExampleItem[] = [
status: 'Out of stock',
statusColor: 'negative',
date: new FdDate(2020, 2, 5),
verified: true
verified: true,
selected: true
},
{
name: 'Astro Phone 6',
Expand Down
10 changes: 10 additions & 0 deletions libs/docs/platform/table/platform-table-docs.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
Consider that in the table with selection column present the overall columns width cannot be less than table
container.
</p>

<p>
You can have preselected rows by providing <code>selectedKey</code> input property for the table with field name
in row object. Any truthy value will be considered as selected.
</p>

<p>
You also can disable selecting for some rows by providing <code>selectableKey</code> input property for the
table with field name in row object. Only <code>false</code> value disables selection.
</p>
</description>
<component-example>
<fdp-platform-table-multiple-row-selection-example></fdp-platform-table-multiple-row-selection-example>
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions libs/platform/src/lib/table/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './table-rows-rearrange-event.model';
export * from './table-row-activate-event.model';
export * from './row-comparator.model';
export * from './table-managed-preset';
export * from './save-rows-event.interface';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class SaveRowsEvent<T> {
/**
* Table save rows event
* @param done Callback function. Call it when newly added items has been saved and new data source fetch is needed.
* @param items Array of newly created items.
*/
constructor(public done: () => void, public items: T[]) {}
}
1 change: 0 additions & 1 deletion libs/platform/src/lib/table/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export * from './interfaces/collection-state.interface';
export * from './interfaces/search-field.interface';
export * from './interfaces/selection-value.interface';
export * from './interfaces/table-state.interface';
export * from './interfaces/save-rows-event.interface';
export * from './interfaces/column-responsive-state.interface';

export * from './models';
10 changes: 10 additions & 0 deletions libs/platform/src/lib/table/table.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@
<ng-container [ngSwitch]="selectionMode">
<ng-container *ngSwitchCase="SELECTION_MODE.SINGLE">
<td
*ngIf="row.value[selectableKey] !== false; else selectionMock"
class="fd-table__cell--fixed fd-table__cell--checkbox"
tabindex="0"
role="rowheader"
Expand All @@ -309,6 +310,7 @@

<ng-container *ngSwitchCase="SELECTION_MODE.MULTIPLE">
<td
*ngIf="row.value[selectableKey] !== false; else selectionMock"
class="fd-table__cell--fixed fd-table__cell--checkbox"
role="cell"
fd-table-cell
Expand All @@ -329,6 +331,14 @@
</ng-container>
</ng-container>

<ng-template #selectionMock>
<td
class="fd-table__cell--fixed fd-table__cell--checkbox"
role="rowheader"
fd-table-cell
></td>
</ng-template>

<td
*ngFor="let column of _visibleColumns; let colIdx = index"
fd-table-cell
Expand Down
61 changes: 45 additions & 16 deletions libs/platform/src/lib/table/table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import { PopoverComponent } from '@fundamental-ngx/core/popover';
import { cloneDeep, get } from 'lodash-es';
import { Nullable } from '@fundamental-ngx/cdk/utils';

import { SaveRowsEvent } from './interfaces/save-rows-event.interface';
import { EditableTableCell } from './table-cell.class';
import { TableResponsiveService } from './table-responsive.service';

Expand Down Expand Up @@ -84,7 +83,8 @@ import {
TableRowSelectionChangeEvent,
TableRowsRearrangeEvent,
TableRowToggleOpenStateEvent,
TableSortChangeEvent
TableSortChangeEvent,
SaveRowsEvent
} from './models';
import { TableColumnResizeService } from './table-column-resize.service';
import {
Expand Down Expand Up @@ -360,6 +360,32 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
/** @hidden */
private _forceSemanticHighlighting = false;

/** Value with the key of the row item's field to enable selecting. */
@Input()
set selectedKey(value: string) {
this._selectedKey = value;
}

get selectedKey(): string {
return this._selectedKey;
}

/** @hidden */
private _selectedKey: string;

/** Value with the key of the row item's field to enable selecting. */
@Input()
set selectableKey(value: string) {
this._selectableKey = value;
}

get selectableKey(): string {
return this._selectableKey;
}

/** @hidden */
private _selectableKey: string;

/**
* Tracking function that will be used to check the differences in data changes.
* Used similarly to `ngFor` `trackBy` function.
Expand Down Expand Up @@ -1086,7 +1112,7 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
toggleSelectableRow(rowIndex: number): void {
const row = this._tableRows[rowIndex];

if (!row) {
if (!row || row.value[this.selectableKey] === false) {
return;
}

Expand Down Expand Up @@ -1156,16 +1182,17 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
* Adds empty row for editing at the beginning of the rows array.
*/
addRow(): void {
const newRow = this._buildNewRowSkeleton();
this._forceSemanticHighlighting = true;

const newRow = this._buildNewRowSkeleton();
newRow[this.semanticHighlighting] = EDITABLE_ROW_SEMANTIC_STATE;

this._addedItems.unshift(newRow);

const newRows = this._createTableRowsByDataSourceItems([newRow]);
this._newTableRows = [...newRows, ...this._newTableRows];

this._setTableRows(this._dataSourceTableRows);
this._setTableRows();
this.emptyRowAdded.emit();
}

Expand All @@ -1179,12 +1206,9 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
* Emits save event and resets editable rows array.
*/
saveRows(): void {
const event: SaveRowsEvent<T> = {
items: [...this._addedItems],
done: () => {
this._tableDataSource.fetch(this.getTableState());
}
};
const event = new SaveRowsEvent<T>(() => {
this._tableDataSource.fetch(this.getTableState());
}, [...this._addedItems]);

const forms = [...this.customEditableCells.toArray(), ...this.editableCells.toArray()].map((t) => t.form);

Expand Down Expand Up @@ -1751,7 +1775,12 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,

return source.map((item: T, index: number) => {
const isNewItem = this._addedItems.includes(item);
const row = new TableRow(TableRowType.ITEM, !!selectedRowsMap.get(item), index, item);
const row = new TableRow(
TableRowType.ITEM,
item[this.selectedKey] ?? !!selectedRowsMap.get(item),
index,
item
);
row.navigatable = this._isRowNavigatable(item, this.rowNavigatable);
row.state = isNewItem ? 'editable' : 'readonly';
return row;
Expand All @@ -1771,7 +1800,7 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
item[this.relationKey].length;
const row = new TableRow(
hasChildren ? TableRowType.TREE : TableRowType.ITEM,
!!selectedRowsMap.get(item),
item[this.selectedKey] ?? !!selectedRowsMap.get(item),
index,
item
);
Expand Down Expand Up @@ -1821,7 +1850,7 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
}

/** @hidden */
private _setTableRows(rows: TableRow[]): void {
private _setTableRows(rows = this._dataSourceTableRows): void {
this._dataSourceTableRows = rows;
this._tableRows = [...this._newTableRows, ...this._dataSourceTableRows];
this._onTableRowsChanged();
Expand Down Expand Up @@ -2248,7 +2277,7 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,

/** @hidden */
private _isSelectableRow(row: TableRow): boolean {
return this._isItemRow(row) || this._isTreeRow(row);
return (this._isItemRow(row) || this._isTreeRow(row)) && row.value[this.selectableKey] !== false;
}

/** @hidden */
Expand Down Expand Up @@ -2442,7 +2471,7 @@ export class TableComponent<T = any> extends Table<T> implements AfterViewInit,
this._newTableRows = [];
this._addedItems = [];
this._forceSemanticHighlighting = false;
this._setTableRows(this._dataSourceTableRows);
this._setTableRows();
}

/** @hidden */
Expand Down
3 changes: 1 addition & 2 deletions libs/platform/src/lib/table/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import { EventEmitter, Injector } from '@angular/core';
import { PresetManagedComponent } from '@fundamental-ngx/platform/shared';
import { Observable } from 'rxjs';

import { SaveRowsEvent } from './interfaces/save-rows-event.interface';
import { TableState } from './interfaces/table-state.interface';
import { CollectionSort } from './interfaces/collection-sort.interface';
import { CollectionFilter } from './interfaces/collection-filter.interface';
import { CollectionGroup } from './interfaces/collection-group.interface';
import { SearchInput } from './interfaces/search-field.interface';
import { TableColumn } from './components/table-column/table-column';
import { TableDataSource } from './domain';
import { PlatformTableManagedPreset } from './models';
import { PlatformTableManagedPreset, SaveRowsEvent } from './models';

export abstract class Table<T = any> implements PresetManagedComponent<PlatformTableManagedPreset> {
abstract readonly name: string;
Expand Down

0 comments on commit e66901b

Please sign in to comment.