Skip to content

Commit 7ae8ca7

Browse files
committed
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 634cb7b commit 7ae8ca7

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
@@ -17,6 +17,7 @@ import {
1717
Input,
1818
IterableDiffer,
1919
IterableDiffers,
20+
model,
2021
numberAttribute,
2122
OnDestroy,
2223
OnInit,
@@ -195,7 +196,7 @@ export class DatatableComponent<TRow extends Row = any>
195196
* represented as selected in the grid.
196197
* Default value: `[]`
197198
*/
198-
@Input() selected: TRow[] = [];
199+
readonly selected = model<TRow[]>([]);
199200

200201
/**
201202
* Enable vertical scrollbars
@@ -494,6 +495,19 @@ export class DatatableComponent<TRow extends Row = any>
494495

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

@@ -683,15 +697,16 @@ export class DatatableComponent<TRow extends Row = any>
683697
* Returns if all rows are selected.
684698
*/
685699
get allRowsSelected(): boolean {
686-
let allRowsSelected = this.rows && this.selected && this.selected.length === this.rows.length;
700+
const selected = this.selected();
701+
let allRowsSelected = this.rows && selected && selected.length === this.rows.length;
687702

688703
if (this.bodyComponent && this.selectAllRowsOnPage()) {
689704
const indexes = this.bodyComponent.indexes;
690705
const rowsOnPage = indexes().last - indexes().first;
691-
allRowsSelected = this.selected.length === rowsOnPage;
706+
allRowsSelected = selected.length === rowsOnPage;
692707
}
693708

694-
return this.selected && this.rows?.length !== 0 && allRowsSelected;
709+
return selected && this.rows?.length !== 0 && allRowsSelected;
695710
}
696711

697712
element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;
@@ -1049,9 +1064,9 @@ export class DatatableComponent<TRow extends Row = any>
10491064
});
10501065

10511066
if (this.selectAllRowsOnPage()) {
1052-
this.selected = [];
1067+
this.selected.set([]);
10531068
this.select.emit({
1054-
selected: this.selected
1069+
selected: this.selected()
10551070
});
10561071
}
10571072
}
@@ -1189,9 +1204,9 @@ export class DatatableComponent<TRow extends Row = any>
11891204
onColumnSort(event: SortEvent): void {
11901205
// clean selected rows
11911206
if (this.selectAllRowsOnPage()) {
1192-
this.selected = [];
1207+
this.selected.set([]);
11931208
this.select.emit({
1194-
selected: this.selected
1209+
selected: this.selected()
11951210
});
11961211
}
11971212

@@ -1233,14 +1248,13 @@ export class DatatableComponent<TRow extends Row = any>
12331248
// before we splice, chk if we currently have all selected
12341249
const first = this.bodyComponent.indexes().first;
12351250
const last = this.bodyComponent.indexes().last;
1236-
const allSelected = this.selected.length === last - first;
1237-
1238-
// remove all existing either way
1239-
this.selected = [];
1251+
const allSelected = this.selected().length === last - first;
12401252

12411253
// do the opposite here
12421254
if (!allSelected) {
1243-
this.selected.push(...this._internalRows.slice(first, last).filter(row => !!row));
1255+
this.selected.set(this._internalRows.slice(first, last).filter(row => !!row) as TRow[]);
1256+
} else {
1257+
this.selected.set([]);
12441258
}
12451259
} else {
12461260
let relevantRows: TRow[];
@@ -1253,25 +1267,24 @@ export class DatatableComponent<TRow extends Row = any>
12531267
relevantRows = this.rows.filter(row => !!row);
12541268
}
12551269
// before we splice, chk if we currently have all selected
1256-
const allSelected = this.selected.length === relevantRows.length;
1257-
// remove all existing either way
1258-
this.selected = [];
1270+
const allSelected = this.selected().length === relevantRows.length;
12591271
// do the opposite here
12601272
if (!allSelected) {
1261-
this.selected.push(...relevantRows);
1273+
this.selected.set(relevantRows);
1274+
} else {
1275+
this.selected.set([]);
12621276
}
12631277
}
12641278

12651279
this.select.emit({
1266-
selected: this.selected
1280+
selected: this.selected()
12671281
});
12681282
}
12691283

12701284
/**
12711285
* A row was selected from body
12721286
*/
12731287
onBodySelect(selected: TRow[]): void {
1274-
this.selected.splice(0, this.selected.length, ...selected);
12751288
this.select.emit({ selected });
12761289
}
12771290

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)