[ADF-2541] reset datatable selection when rows are changed from code (#3410)

* reset selection when rows are replaced from code

* code fixes

* unit test updates

* visualise selection count for testing purposes

* make row selection api public

* remove question mark from the event name
This commit is contained in:
Denys Vuika
2018-05-30 11:53:12 +01:00
committed by Eugenio Romano
parent 7e59b24f2c
commit 3162a73f61
8 changed files with 98 additions and 64 deletions

View File

@@ -1,30 +1,34 @@
<div class="p-10">
<adf-datatable
[data]="data"
[selectionMode]="selectionMode"
[multiselect]="multiselect"
[actions]="true"
rowStyleClass="custom-row-style"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)"
(row-click)="onRowClick($event)"
(row-dblclick)="onRowDblClick($event)">
<!-- HTML column definition demo -->
<!--
<data-columns>
<data-column type="image" key="icon" [sortable]="false"></data-column>
<data-column key="id" title="Id"></data-column>
<data-column key="createdOn" title="Created"></data-column>
<data-column key="name" title="Name" class="full-width name-column"></data-column>
<data-column key="createdBy.name" title="Created By"></data-column>
</data-columns>
-->
</adf-datatable>
<adf-datatable
#dataTable
[data]="data"
[selectionMode]="selectionMode"
[multiselect]="multiselect"
[actions]="true"
rowStyleClass="custom-row-style"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)"
(row-click)="onRowClick($event)"
(row-dblclick)="onRowDblClick($event)">
<!-- HTML column definition demo -->
<!--
<data-columns>
<data-column type="image" key="icon" [sortable]="false"></data-column>
<data-column key="id" title="Id"></data-column>
<data-column key="createdOn" title="Created"></data-column>
<data-column key="name" title="Name" class="full-width name-column"></data-column>
<data-column key="createdBy.name" title="Created By"></data-column>
</data-columns>
-->
</adf-datatable>
<div>
Selected items: {{ dataTable.selection?.length }}
</div>
<div class="p-10" data-automation-id="multiselect">
<div data-automation-id="multiselect">
<mat-checkbox [(ngModel)]="multiselect">{{ 'DATATABLE.MULTISELECT'| translate }}</mat-checkbox>
</div>
<div class="p-10">
<div>
<p>{{ 'DATATABLE.MULTISELECT_DESCRIPTION'| translate }}</p>
<mat-form-field>
<mat-select placeholder="Selection Mode" [(ngModel)]="selectionMode" name="food">
@@ -34,7 +38,7 @@
</mat-select>
</mat-form-field>
</div>
<div class="p-10">
<div>
<button mat-raised-button (click)="reset()">{{ 'DATATABLE.RESET_DEFAULT'| translate }}</button>
<button mat-raised-button (click)="addRow()">{{ 'DATATABLE.ADD_ROW'| translate }}</button>
<button mat-raised-button (click)="replaceRows()">{{ 'DATATABLE.REPLACE_ROWS'| translate }}</button>

View File

@@ -1,16 +0,0 @@
adf-datatable ::ng-deep .custom-row-style.alfresco-datatable__row:focus {
outline-offset: -1px;
outline-width: 1px;
outline-color: green;
outline-style: solid;
}
adf-datatable ::ng-deep .custom-row-style.alfresco-datatable__row--selected {
color: green;
}
adf-datatable ::ng-deep table {
max-width: 100%;
overflow: hidden;
white-space: normal !important;
}

View File

@@ -22,8 +22,7 @@ import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-datatable',
templateUrl: './datatable.component.html',
styleUrls: ['./datatable.component.scss']
templateUrl: './datatable.component.html'
})
export class DataTableComponent {
@@ -41,8 +40,8 @@ export class DataTableComponent {
private _imageUrl = 'http://placehold.it/140x100';
private _createdBy: any = {
name: 'Denys Vuika',
email: 'denys.vuika@alfresco.com'
name: 'Administrator',
email: 'admin@alfresco.com'
};
constructor(private apiService: AlfrescoApiService, private logService: LogService) {

View File

@@ -14,6 +14,12 @@ and [Tasklist](../process-services/task-list.component.md) components.
| ---- | ---- | ----------- |
| selectedRow | DataRow | The data for the currently selected row. |
## Events
| Name | Type | Description |
| ---- | ---- | ----------- |
| rowsChanged | `Subject<Array<DataRow>>` | Raised when data adapter gets new rows. |
## Methods
[`getRows(): Array<DataRow>;`](../../lib/core/datatable/data/data-row.model.ts)<br/>
@@ -27,11 +33,11 @@ Get/set an array of column specifications.
`getValue(row: DataRow, col: DataColumn): any;`<br/>
Get the data value from a specific table cell.
`getSorting(): DataSorting;`
`setSorting(sorting: DataSorting): void;`
`getSorting(): DataSorting;`<br/>
`setSorting(sorting: DataSorting): void;`<br/>
Get/set the sorting key and direction (ascending or descending).
`sort(key?: string, direction?: string): void;`
`sort(key?: string, direction?: string): void;`<br/>
Sort the table with a specified key and direction (ascending or descending).
## Details

View File

@@ -484,15 +484,6 @@ describe('DataTable', () => {
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
});
it('should load data table on onChange', () => {
let table = new DataTableComponent(null, null);
let data = new ObjectDataTableAdapter([], []);
expect(table.data).toBeUndefined();
table.ngOnChanges({'data': new SimpleChange('123', data, true)});
expect(table.data).toEqual(data);
});
it('should initialize with custom data', () => {
let data = new ObjectDataTableAdapter([], []);
dataTable.data = data;
@@ -690,6 +681,22 @@ describe('DataTable', () => {
expect(dataTable.isSelectAllChecked).toBeFalsy();
});
it('should reset selection upon data rows change', () => {
let data = new ObjectDataTableAdapter([{}, {}, {}], []);
dataTable.data = data;
dataTable.multiselect = true;
dataTable.ngAfterContentInit();
dataTable.onSelectAllClick(<MatCheckboxChange> { checked: true });
expect(dataTable.selection.every(entry => entry.isSelected));
data.setRows([]);
fixture.detectChanges();
expect(dataTable.selection.every(entry => !entry.isSelected));
});
it('should update rows on "select all" click', () => {
let data = new ObjectDataTableAdapter([{}, {}, {}], []);
let rows = data.getRows();

View File

@@ -20,9 +20,7 @@ import {
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation, OnDestroy
} from '@angular/core';
import { MatCheckboxChange } from '@angular/material';
import { Subscription } from 'rxjs/Subscription';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import { Subscription, Observable, Observer } from 'rxjs/Rx';
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
import { DataColumn } from '../../data/data-column.model';
import { DataRowEvent } from '../../data/data-row-event.model';
@@ -168,6 +166,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
private subscriptions: Subscription[] = [];
private singleClickStreamSub: Subscription;
private multiClickStreamSub: Subscription;
private dataRowsChanged: Subscription;
constructor(private elementRef: ElementRef,
differs: IterableDiffers,
@@ -196,6 +195,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
this.initTable();
} else {
this.data = changes['data'].currentValue;
this.setupData(this.data);
}
return;
}
@@ -205,6 +205,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
this.initTable();
} else {
this.setTableRows(changes['rows'].currentValue);
this.setupData(this.data);
}
return;
}
@@ -293,15 +294,34 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
private initTable() {
this.data = new ObjectDataTableAdapter(this.rows, this.schema);
this.setupData(this.data);
this.rowMenuCache = {};
}
private setupData(adapter: DataTableAdapter) {
if (this.dataRowsChanged) {
this.dataRowsChanged.unsubscribe();
this.dataRowsChanged = null;
}
this.resetSelection();
if (adapter && adapter.rowsChanged) {
this.dataRowsChanged = adapter.rowsChanged.subscribe(() => {
this.resetSelection();
});
}
}
isTableEmpty() {
return this.data === undefined || this.data === null;
}
private setTableRows(rows) {
private setTableRows(rows: any[]) {
if (this.data) {
if (rows && rows.length > 0) {
this.resetSelection();
}
this.data.setRows(this.convertToRowsData(rows));
}
}
@@ -560,7 +580,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
}
}
private selectRow(row: DataRow, value: boolean) {
selectRow(row: DataRow, value: boolean) {
if (row) {
row.isSelected = value;
const idx = this.selection.indexOf(row);
@@ -588,8 +608,8 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
}
getSortableColumns() {
return this.data.getColumns().filter((currentColum) => {
return currentColum.sortable === true;
return this.data.getColumns().filter(column => {
return column.sortable === true;
});
}
@@ -625,7 +645,13 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
ngOnDestroy() {
this.unsubscribeClickStream();
this.subscriptions.forEach(s => s.unsubscribe());
this.subscriptions = [];
if (this.dataRowsChanged) {
this.dataRowsChanged.unsubscribe();
this.dataRowsChanged = null;
}
}
}

View File

@@ -18,8 +18,11 @@
import { DataColumn } from './data-column.model';
import { DataRow } from './data-row.model';
import { DataSorting } from './data-sorting.model';
import { Subject } from 'rxjs/Rx';
export interface DataTableAdapter {
rowsChanged?: Subject<Array<DataRow>>;
selectedRow: DataRow;
getRows(): Array<DataRow>;
setRows(rows: Array<DataRow>): void;

View File

@@ -21,6 +21,7 @@ import { ObjectDataRow } from './object-datarow.model';
import { ObjectDataColumn } from './object-datacolumn.model';
import { DataSorting } from './data-sorting.model';
import { DataTableAdapter } from './datatable-adapter';
import { Subject } from 'rxjs/Subject';
// Simple implementation of the DataTableAdapter interface.
export class ObjectDataTableAdapter implements DataTableAdapter {
@@ -30,6 +31,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
private _columns: DataColumn[];
selectedRow: DataRow;
rowsChanged: Subject<Array<DataRow>>;
static generateSchema(data: any[]) {
let schema = [];
@@ -75,6 +77,8 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
this.sort(sortable[0].key, 'asc');
}
}
this.rowsChanged = new Subject<Array<DataRow>>();
}
getRows(): Array<DataRow> {
@@ -84,6 +88,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
setRows(rows: Array<DataRow>) {
this._rows = rows || [];
this.sort();
this.rowsChanged.next(this._rows);
}
getColumns(): Array<DataColumn> {