Skip to content

Commit 8abd4b6

Browse files
spike-rabbitfh1ch
authored andcommitted
feat: convert selected to signal model with two-way binding
Convert the selected input to a signal model. BREAKING CHANGE: The selected input no longer mutates the original array passed to the component. Applications that rely on the array being updated in place must switch to two-way binding with [(selected)] to maintain reactivity. DEPRECATED: The `DatatableComponent.select` output is deprecated; use (selectedChange) or two-way binding instead . Before: ```html <ngx-datatable [selected]="mySelection" (select)="onSelect($event)"></ngx-datatable> ``` After: ```html <ngx-datatable [(selected)]="mySelection" (selectedChange)="onSelect({selected: $event})"></ngx-datatable> <!-- or --> <ngx-datatable [(selected)]="mySelection"></ngx-datatable> ```
1 parent 9039c86 commit 8abd4b6

File tree

4 files changed

+40
-31
lines changed

4 files changed

+40
-31
lines changed

projects/ngx-datatable/src/lib/components/datatable.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
[offsetX]="_offsetX"
5252
[rowDetail]="rowDetail"
5353
[groupHeader]="groupHeader"
54-
[selected]="selected"
5554
[innerWidth]="_innerWidth"
5655
[bodyHeight]="bodyHeight"
5756
[selectionType]="selectionType()"
@@ -72,6 +71,7 @@
7271
[rowDragEvents]="rowDragEvents"
7372
[rowDefTemplate]="rowDefTemplate"
7473
[cssClasses]="cssClasses"
74+
[(selected)]="selected"
7575
(page)="onBodyPage($event)"
7676
(activate)="activate.emit($event)"
7777
(rowContextmenu)="onRowContextmenu($event)"
@@ -105,7 +105,7 @@
105105
[pagerLeftArrowIcon]="cssClasses.pagerLeftArrow"
106106
[pagerRightArrowIcon]="cssClasses.pagerRightArrow"
107107
[pagerPreviousIcon]="cssClasses.pagerPrevious"
108-
[selectedCount]="selected.length"
108+
[selectedCount]="selected().length"
109109
[selectedMessage]="!!selectionType() && (messages.selectedMessage ?? 'selected')"
110110
[pagerNextIcon]="cssClasses.pagerNext"
111111
(page)="onFooterPage($event)"

projects/ngx-datatable/src/lib/components/datatable.component.ts

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
Input,
1717
IterableDiffer,
1818
IterableDiffers,
19+
model,
1920
numberAttribute,
2021
OnDestroy,
2122
OnInit,
@@ -194,7 +195,7 @@ export class DatatableComponent<TRow extends Row = any>
194195
* represented as selected in the grid.
195196
* Default value: `[]`
196197
*/
197-
@Input() selected: TRow[] = [];
198+
readonly selected = model<TRow[]>([]);
198199

199200
/**
200201
* Enable vertical scrollbars
@@ -493,6 +494,19 @@ export class DatatableComponent<TRow extends Row = any>
493494

494495
/**
495496
* A cell or row was selected.
497+
* @deprecated Use two-way binding on `selected` instead.
498+
*
499+
* Before:
500+
* ```html
501+
* <ngx-datatable [selected]="mySelection" (select)="onSelect($event)"></ngx-datatable>
502+
* ```
503+
*
504+
* After:
505+
* ```html
506+
* <ngx-datatable [selected]="mySelection" (selectedChange)="onSelect({selected: $event})"></ngx-datatable>
507+
* <!-- or -->
508+
* <ngx-datatable [(selected)]="mySelection"></ngx-datatable>
509+
* ```
496510
*/
497511
readonly select = output<SelectEvent<TRow>>();
498512

@@ -682,15 +696,16 @@ export class DatatableComponent<TRow extends Row = any>
682696
* Returns if all rows are selected.
683697
*/
684698
get allRowsSelected(): boolean {
685-
let allRowsSelected = this.rows && this.selected && this.selected.length === this.rows.length;
699+
const selected = this.selected();
700+
let allRowsSelected = this.rows && selected && selected.length === this.rows.length;
686701

687702
if (this.bodyComponent && this.selectAllRowsOnPage()) {
688703
const indexes = this.bodyComponent.indexes;
689704
const rowsOnPage = indexes().last - indexes().first;
690-
allRowsSelected = this.selected.length === rowsOnPage;
705+
allRowsSelected = selected.length === rowsOnPage;
691706
}
692707

693-
return this.selected && this.rows?.length !== 0 && allRowsSelected;
708+
return selected && this.rows?.length !== 0 && allRowsSelected;
694709
}
695710

696711
element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;
@@ -1046,9 +1061,9 @@ export class DatatableComponent<TRow extends Row = any>
10461061
});
10471062

10481063
if (this.selectAllRowsOnPage()) {
1049-
this.selected = [];
1064+
this.selected.set([]);
10501065
this.select.emit({
1051-
selected: this.selected
1066+
selected: this.selected()
10521067
});
10531068
}
10541069
}
@@ -1186,9 +1201,9 @@ export class DatatableComponent<TRow extends Row = any>
11861201
onColumnSort(event: SortEvent): void {
11871202
// clean selected rows
11881203
if (this.selectAllRowsOnPage()) {
1189-
this.selected = [];
1204+
this.selected.set([]);
11901205
this.select.emit({
1191-
selected: this.selected
1206+
selected: this.selected()
11921207
});
11931208
}
11941209

@@ -1230,14 +1245,13 @@ export class DatatableComponent<TRow extends Row = any>
12301245
// before we splice, chk if we currently have all selected
12311246
const first = this.bodyComponent.indexes().first;
12321247
const last = this.bodyComponent.indexes().last;
1233-
const allSelected = this.selected.length === last - first;
1234-
1235-
// remove all existing either way
1236-
this.selected = [];
1248+
const allSelected = this.selected().length === last - first;
12371249

12381250
// do the opposite here
12391251
if (!allSelected) {
1240-
this.selected.push(...this._internalRows.slice(first, last).filter(row => !!row));
1252+
this.selected.set(this._internalRows.slice(first, last).filter(row => !!row) as TRow[]);
1253+
} else {
1254+
this.selected.set([]);
12411255
}
12421256
} else {
12431257
let relevantRows: TRow[];
@@ -1250,25 +1264,24 @@ export class DatatableComponent<TRow extends Row = any>
12501264
relevantRows = this.rows.filter(row => !!row);
12511265
}
12521266
// before we splice, chk if we currently have all selected
1253-
const allSelected = this.selected.length === relevantRows.length;
1254-
// remove all existing either way
1255-
this.selected = [];
1267+
const allSelected = this.selected().length === relevantRows.length;
12561268
// do the opposite here
12571269
if (!allSelected) {
1258-
this.selected.push(...relevantRows);
1270+
this.selected.set(relevantRows);
1271+
} else {
1272+
this.selected.set([]);
12591273
}
12601274
}
12611275

12621276
this.select.emit({
1263-
selected: this.selected
1277+
selected: this.selected()
12641278
});
12651279
}
12661280

12671281
/**
12681282
* A row was selected from body
12691283
*/
12701284
onBodySelect(selected: TRow[]): void {
1271-
this.selected.splice(0, this.selected.length, ...selected);
12721285
this.select.emit({ selected });
12731286
}
12741287

projects/ngx-datatable/src/lib/types/public.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ export const SelectionType = {
238238

239239
export type SelectionType = (typeof SelectionType)[keyof typeof SelectionType];
240240

241+
/** @deprecated. Use two-way binding instead. See {@link DatatableComponent.select} */
241242
export interface SelectEvent<TRow> {
242243
selected: TRow[];
243244
}

src/app/selection/selection-single.component.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { Component, inject } from '@angular/core';
2-
import {
3-
ActivateEvent,
4-
DatatableComponent,
5-
SelectEvent,
6-
TableColumn
7-
} from '@siemens/ngx-datatable';
2+
import { ActivateEvent, DatatableComponent, TableColumn } from '@siemens/ngx-datatable';
83

94
import { Employee } from '../data.model';
105
import { DataService } from '../data.service';
@@ -43,9 +38,9 @@ import { DataService } from '../data.service';
4338
[headerHeight]="50"
4439
[footerHeight]="50"
4540
[limit]="5"
46-
[selected]="selected"
41+
[(selected)]="selected"
4742
(activate)="onActivate($event)"
48-
(select)="onSelect($event)"
43+
(selectedChange)="onSelect($event)"
4944
/>
5045
</div>
5146
@@ -80,9 +75,9 @@ export class SingleSelectionComponent {
8075
});
8176
}
8277

83-
onSelect({ selected }: SelectEvent<Employee>) {
78+
onSelect(employees: Employee[]) {
8479
// eslint-disable-next-line no-console
85-
console.log('Select Event', selected, this.selected);
80+
console.log('Select Event', employees);
8681
}
8782

8883
onActivate(event: ActivateEvent<Employee>) {

0 commit comments

Comments
 (0)