@@ -10,7 +10,10 @@ import { EntityFieldEditComponent } from "../entity-field-edit/entity-field-edit
1010import { EntityFieldLabelComponent } from "../entity-field-label/entity-field-label.component" ;
1111import { EntityFieldViewComponent } from "../entity-field-view/entity-field-view.component" ;
1212import { ListPaginatorComponent } from "./list-paginator/list-paginator.component" ;
13- import { MatCheckboxModule } from "@angular/material/checkbox" ;
13+ import {
14+ MatCheckboxChange ,
15+ MatCheckboxModule ,
16+ } from "@angular/material/checkbox" ;
1417import { MatProgressBarModule } from "@angular/material/progress-bar" ;
1518import { MatSlideToggleModule } from "@angular/material/slide-toggle" ;
1619import {
@@ -77,6 +80,8 @@ export class EntitiesTableComponent<T extends Entity> {
7780 this . updateFilteredData ( ) ;
7881 this . isLoading = false ;
7982 }
83+ private lastSelectedIndex : number = null ;
84+ private lastSelection : boolean = null ;
8085 _records : T [ ] = [ ] ;
8186 /** data displayed in the template's table */
8287 recordsDataSource : MatTableDataSource < TableRow < T > > ;
@@ -235,7 +240,6 @@ export class EntitiesTableComponent<T extends Entity> {
235240 this . selectedRecords . splice ( index , 1 ) ;
236241 }
237242 }
238-
239243 this . selectedRecordsChange . emit ( this . selectedRecords ) ;
240244 }
241245
@@ -263,7 +267,6 @@ export class EntitiesTableComponent<T extends Entity> {
263267 if ( row . formGroup && ! row . formGroup . disabled ) {
264268 return ;
265269 }
266-
267270 if ( this . _selectable ) {
268271 this . selectRow ( row , ! this . selectedRecords ?. includes ( row . record ) ) ;
269272 return ;
@@ -273,6 +276,79 @@ export class EntitiesTableComponent<T extends Entity> {
273276 this . entityClick . emit ( row . record ) ;
274277 }
275278
279+ onRowMouseDown ( event : MouseEvent , row : TableRow < T > ) {
280+ if ( ! this . _selectable ) {
281+ this . onRowClick ( row ) ;
282+ return ;
283+ }
284+
285+ // Find the index of the row in the sorted and filtered data
286+ const sortedData = this . recordsDataSource . sortData (
287+ this . recordsDataSource . data ,
288+ this . recordsDataSource . sort ,
289+ ) ;
290+ const currentIndex = sortedData . indexOf ( row ) ;
291+
292+ const isCheckboxClick =
293+ event . target instanceof HTMLInputElement &&
294+ event . target . type === "checkbox" ;
295+
296+ if ( event . shiftKey && this . lastSelectedIndex !== null ) {
297+ const start = Math . min ( this . lastSelectedIndex , currentIndex ) ;
298+ const end = Math . max ( this . lastSelectedIndex , currentIndex ) ;
299+ const shouldCheck =
300+ this . lastSelection !== null
301+ ? ! this . lastSelection
302+ : ! this . selectedRecords . includes ( row . record ) ;
303+
304+ for ( let i = start ; i <= end ; i ++ ) {
305+ const rowToSelect = sortedData [ i ] ;
306+ const isSelected = this . selectedRecords . includes ( rowToSelect . record ) ;
307+
308+ if ( shouldCheck && ! isSelected ) {
309+ this . selectedRecords . push ( rowToSelect . record ) ;
310+ } else if ( ! shouldCheck && isSelected ) {
311+ this . selectedRecords = this . selectedRecords . filter (
312+ ( record ) => record !== rowToSelect . record ,
313+ ) ;
314+ }
315+ }
316+ this . selectedRecordsChange . emit ( this . selectedRecords ) ;
317+ } else {
318+ const isSelected = this . selectedRecords . includes ( row . record ) ;
319+ this . selectRow ( row , ! isSelected ) ;
320+ this . lastSelectedIndex = currentIndex ;
321+ this . lastSelection = isSelected ;
322+ }
323+
324+ if ( isCheckboxClick ) {
325+ this . onRowClick ( row ) ;
326+ }
327+ }
328+
329+ onRowSelect ( event : MatCheckboxChange , row : TableRow < T > ) {
330+ this . selectRow ( row , event . checked ) ;
331+ }
332+
333+ selectAllRows ( event : MatCheckboxChange ) {
334+ if ( event . checked ) {
335+ this . selectedRecords = this . recordsDataSource . data . map (
336+ ( row ) => row . record ,
337+ ) ;
338+ } else {
339+ this . selectedRecords = [ ] ;
340+ }
341+ this . selectedRecordsChange . emit ( this . selectedRecords ) ;
342+ }
343+
344+ isAllSelected ( ) {
345+ return this . selectedRecords . length === this . recordsDataSource . data . length ;
346+ }
347+
348+ isIndeterminate ( ) {
349+ return this . selectedRecords . length > 0 && ! this . isAllSelected ( ) ;
350+ }
351+
276352 showEntity ( entity : T ) {
277353 switch ( this . clickMode ) {
278354 case "popup" :
0 commit comments