mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[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:
committed by
Eugenio Romano
parent
7e59b24f2c
commit
3162a73f61
@@ -1,30 +1,34 @@
|
|||||||
<div class="p-10">
|
<adf-datatable
|
||||||
<adf-datatable
|
#dataTable
|
||||||
[data]="data"
|
[data]="data"
|
||||||
[selectionMode]="selectionMode"
|
[selectionMode]="selectionMode"
|
||||||
[multiselect]="multiselect"
|
[multiselect]="multiselect"
|
||||||
[actions]="true"
|
[actions]="true"
|
||||||
rowStyleClass="custom-row-style"
|
rowStyleClass="custom-row-style"
|
||||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||||
(executeRowAction)="onExecuteRowAction($event)"
|
(executeRowAction)="onExecuteRowAction($event)"
|
||||||
(row-click)="onRowClick($event)"
|
(row-click)="onRowClick($event)"
|
||||||
(row-dblclick)="onRowDblClick($event)">
|
(row-dblclick)="onRowDblClick($event)">
|
||||||
<!-- HTML column definition demo -->
|
<!-- HTML column definition demo -->
|
||||||
<!--
|
<!--
|
||||||
<data-columns>
|
<data-columns>
|
||||||
<data-column type="image" key="icon" [sortable]="false"></data-column>
|
<data-column type="image" key="icon" [sortable]="false"></data-column>
|
||||||
<data-column key="id" title="Id"></data-column>
|
<data-column key="id" title="Id"></data-column>
|
||||||
<data-column key="createdOn" title="Created"></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="name" title="Name" class="full-width name-column"></data-column>
|
||||||
<data-column key="createdBy.name" title="Created By"></data-column>
|
<data-column key="createdBy.name" title="Created By"></data-column>
|
||||||
</data-columns>
|
</data-columns>
|
||||||
-->
|
-->
|
||||||
</adf-datatable>
|
</adf-datatable>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Selected items: {{ dataTable.selection?.length }}
|
||||||
</div>
|
</div>
|
||||||
<div class="p-10" data-automation-id="multiselect">
|
|
||||||
|
<div data-automation-id="multiselect">
|
||||||
<mat-checkbox [(ngModel)]="multiselect">{{ 'DATATABLE.MULTISELECT'| translate }}</mat-checkbox>
|
<mat-checkbox [(ngModel)]="multiselect">{{ 'DATATABLE.MULTISELECT'| translate }}</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-10">
|
<div>
|
||||||
<p>{{ 'DATATABLE.MULTISELECT_DESCRIPTION'| translate }}</p>
|
<p>{{ 'DATATABLE.MULTISELECT_DESCRIPTION'| translate }}</p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-select placeholder="Selection Mode" [(ngModel)]="selectionMode" name="food">
|
<mat-select placeholder="Selection Mode" [(ngModel)]="selectionMode" name="food">
|
||||||
@@ -34,7 +38,7 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-10">
|
<div>
|
||||||
<button mat-raised-button (click)="reset()">{{ 'DATATABLE.RESET_DEFAULT'| translate }}</button>
|
<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)="addRow()">{{ 'DATATABLE.ADD_ROW'| translate }}</button>
|
||||||
<button mat-raised-button (click)="replaceRows()">{{ 'DATATABLE.REPLACE_ROWS'| translate }}</button>
|
<button mat-raised-button (click)="replaceRows()">{{ 'DATATABLE.REPLACE_ROWS'| translate }}</button>
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
@@ -22,8 +22,7 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-datatable',
|
selector: 'app-datatable',
|
||||||
templateUrl: './datatable.component.html',
|
templateUrl: './datatable.component.html'
|
||||||
styleUrls: ['./datatable.component.scss']
|
|
||||||
})
|
})
|
||||||
export class DataTableComponent {
|
export class DataTableComponent {
|
||||||
|
|
||||||
@@ -41,8 +40,8 @@ export class DataTableComponent {
|
|||||||
|
|
||||||
private _imageUrl = 'http://placehold.it/140x100';
|
private _imageUrl = 'http://placehold.it/140x100';
|
||||||
private _createdBy: any = {
|
private _createdBy: any = {
|
||||||
name: 'Denys Vuika',
|
name: 'Administrator',
|
||||||
email: 'denys.vuika@alfresco.com'
|
email: 'admin@alfresco.com'
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
|
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
|
||||||
|
@@ -14,6 +14,12 @@ and [Tasklist](../process-services/task-list.component.md) components.
|
|||||||
| ---- | ---- | ----------- |
|
| ---- | ---- | ----------- |
|
||||||
| selectedRow | DataRow | The data for the currently selected row. |
|
| 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
|
## Methods
|
||||||
|
|
||||||
[`getRows(): Array<DataRow>;`](../../lib/core/datatable/data/data-row.model.ts)<br/>
|
[`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/>
|
`getValue(row: DataRow, col: DataColumn): any;`<br/>
|
||||||
Get the data value from a specific table cell.
|
Get the data value from a specific table cell.
|
||||||
|
|
||||||
`getSorting(): DataSorting;`
|
`getSorting(): DataSorting;`<br/>
|
||||||
`setSorting(sorting: DataSorting): void;`
|
`setSorting(sorting: DataSorting): void;`<br/>
|
||||||
Get/set the sorting key and direction (ascending or descending).
|
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).
|
Sort the table with a specified key and direction (ascending or descending).
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
@@ -484,15 +484,6 @@ describe('DataTable', () => {
|
|||||||
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
|
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', () => {
|
it('should initialize with custom data', () => {
|
||||||
let data = new ObjectDataTableAdapter([], []);
|
let data = new ObjectDataTableAdapter([], []);
|
||||||
dataTable.data = data;
|
dataTable.data = data;
|
||||||
@@ -690,6 +681,22 @@ describe('DataTable', () => {
|
|||||||
expect(dataTable.isSelectAllChecked).toBeFalsy();
|
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', () => {
|
it('should update rows on "select all" click', () => {
|
||||||
let data = new ObjectDataTableAdapter([{}, {}, {}], []);
|
let data = new ObjectDataTableAdapter([{}, {}, {}], []);
|
||||||
let rows = data.getRows();
|
let rows = data.getRows();
|
||||||
|
@@ -20,9 +20,7 @@ import {
|
|||||||
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation, OnDestroy
|
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation, OnDestroy
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { MatCheckboxChange } from '@angular/material';
|
import { MatCheckboxChange } from '@angular/material';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription, Observable, Observer } from 'rxjs/Rx';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { Observer } from 'rxjs/Observer';
|
|
||||||
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
|
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
|
||||||
import { DataColumn } from '../../data/data-column.model';
|
import { DataColumn } from '../../data/data-column.model';
|
||||||
import { DataRowEvent } from '../../data/data-row-event.model';
|
import { DataRowEvent } from '../../data/data-row-event.model';
|
||||||
@@ -168,6 +166,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
private subscriptions: Subscription[] = [];
|
private subscriptions: Subscription[] = [];
|
||||||
private singleClickStreamSub: Subscription;
|
private singleClickStreamSub: Subscription;
|
||||||
private multiClickStreamSub: Subscription;
|
private multiClickStreamSub: Subscription;
|
||||||
|
private dataRowsChanged: Subscription;
|
||||||
|
|
||||||
constructor(private elementRef: ElementRef,
|
constructor(private elementRef: ElementRef,
|
||||||
differs: IterableDiffers,
|
differs: IterableDiffers,
|
||||||
@@ -196,6 +195,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
this.initTable();
|
this.initTable();
|
||||||
} else {
|
} else {
|
||||||
this.data = changes['data'].currentValue;
|
this.data = changes['data'].currentValue;
|
||||||
|
this.setupData(this.data);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -205,6 +205,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
this.initTable();
|
this.initTable();
|
||||||
} else {
|
} else {
|
||||||
this.setTableRows(changes['rows'].currentValue);
|
this.setTableRows(changes['rows'].currentValue);
|
||||||
|
this.setupData(this.data);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -293,15 +294,34 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
|
|
||||||
private initTable() {
|
private initTable() {
|
||||||
this.data = new ObjectDataTableAdapter(this.rows, this.schema);
|
this.data = new ObjectDataTableAdapter(this.rows, this.schema);
|
||||||
|
this.setupData(this.data);
|
||||||
this.rowMenuCache = {};
|
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() {
|
isTableEmpty() {
|
||||||
return this.data === undefined || this.data === null;
|
return this.data === undefined || this.data === null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTableRows(rows) {
|
private setTableRows(rows: any[]) {
|
||||||
if (this.data) {
|
if (this.data) {
|
||||||
|
if (rows && rows.length > 0) {
|
||||||
|
this.resetSelection();
|
||||||
|
}
|
||||||
this.data.setRows(this.convertToRowsData(rows));
|
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) {
|
if (row) {
|
||||||
row.isSelected = value;
|
row.isSelected = value;
|
||||||
const idx = this.selection.indexOf(row);
|
const idx = this.selection.indexOf(row);
|
||||||
@@ -588,8 +608,8 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSortableColumns() {
|
getSortableColumns() {
|
||||||
return this.data.getColumns().filter((currentColum) => {
|
return this.data.getColumns().filter(column => {
|
||||||
return currentColum.sortable === true;
|
return column.sortable === true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,7 +645,13 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.unsubscribeClickStream();
|
this.unsubscribeClickStream();
|
||||||
|
|
||||||
this.subscriptions.forEach(s => s.unsubscribe());
|
this.subscriptions.forEach(s => s.unsubscribe());
|
||||||
this.subscriptions = [];
|
this.subscriptions = [];
|
||||||
|
|
||||||
|
if (this.dataRowsChanged) {
|
||||||
|
this.dataRowsChanged.unsubscribe();
|
||||||
|
this.dataRowsChanged = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,8 +18,11 @@
|
|||||||
import { DataColumn } from './data-column.model';
|
import { DataColumn } from './data-column.model';
|
||||||
import { DataRow } from './data-row.model';
|
import { DataRow } from './data-row.model';
|
||||||
import { DataSorting } from './data-sorting.model';
|
import { DataSorting } from './data-sorting.model';
|
||||||
|
import { Subject } from 'rxjs/Rx';
|
||||||
|
|
||||||
export interface DataTableAdapter {
|
export interface DataTableAdapter {
|
||||||
|
rowsChanged?: Subject<Array<DataRow>>;
|
||||||
|
|
||||||
selectedRow: DataRow;
|
selectedRow: DataRow;
|
||||||
getRows(): Array<DataRow>;
|
getRows(): Array<DataRow>;
|
||||||
setRows(rows: Array<DataRow>): void;
|
setRows(rows: Array<DataRow>): void;
|
||||||
|
@@ -21,6 +21,7 @@ import { ObjectDataRow } from './object-datarow.model';
|
|||||||
import { ObjectDataColumn } from './object-datacolumn.model';
|
import { ObjectDataColumn } from './object-datacolumn.model';
|
||||||
import { DataSorting } from './data-sorting.model';
|
import { DataSorting } from './data-sorting.model';
|
||||||
import { DataTableAdapter } from './datatable-adapter';
|
import { DataTableAdapter } from './datatable-adapter';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
// Simple implementation of the DataTableAdapter interface.
|
// Simple implementation of the DataTableAdapter interface.
|
||||||
export class ObjectDataTableAdapter implements DataTableAdapter {
|
export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||||
@@ -30,6 +31,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
|||||||
private _columns: DataColumn[];
|
private _columns: DataColumn[];
|
||||||
|
|
||||||
selectedRow: DataRow;
|
selectedRow: DataRow;
|
||||||
|
rowsChanged: Subject<Array<DataRow>>;
|
||||||
|
|
||||||
static generateSchema(data: any[]) {
|
static generateSchema(data: any[]) {
|
||||||
let schema = [];
|
let schema = [];
|
||||||
@@ -75,6 +77,8 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
|||||||
this.sort(sortable[0].key, 'asc');
|
this.sort(sortable[0].key, 'asc');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rowsChanged = new Subject<Array<DataRow>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows(): Array<DataRow> {
|
getRows(): Array<DataRow> {
|
||||||
@@ -84,6 +88,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
|||||||
setRows(rows: Array<DataRow>) {
|
setRows(rows: Array<DataRow>) {
|
||||||
this._rows = rows || [];
|
this._rows = rows || [];
|
||||||
this.sort();
|
this.sort();
|
||||||
|
this.rowsChanged.next(this._rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
getColumns(): Array<DataColumn> {
|
getColumns(): Array<DataColumn> {
|
||||||
|
Reference in New Issue
Block a user