import { Injectable } from "@angular/core"; import { MatCheckboxChange } from "@angular/material/checkbox"; import { cloneDeep } from "lodash"; import { SelectionType } from "../../models"; export interface TableSelectResults { selectedRows: Object; selected: any[]; selectAllChecked: boolean; selectAllIndeterminate: boolean; } @Injectable() export class TableRowSelectService { constructor() {} getSelectedRowsObject(rows: any[], displayedRows: any[], selected: any[], trackByProp: string): Object { let selectedRows: Object = Object.create(null); if (rows.length > 0) { selectedRows = rows.reduce((r, s) => { let rowSelected = false; if (displayedRows != null && selected != null) { rowSelected = displayedRows.some(x => x[trackByProp] === s[trackByProp]) && selected.some(x => x[trackByProp] === s[trackByProp]) } r[s[trackByProp]] = rowSelected; return r }, Object.create(null)); } return selectedRows; } selectAllChanged(event: MatCheckboxChange, rows: any[], displayedRows: any[], trackByProp: string, rowSelectionDisabledProp?: string): TableSelectResults { let selected = []; let selectAllChecked = false; const selectAllIndeterminate = false; if (!event.checked) { selected = []; selectAllChecked = false; } else if (rowSelectionDisabledProp != null) { selected = displayedRows.filter(x => !x[rowSelectionDisabledProp]); selectAllChecked = true; } else { selected = displayedRows; selectAllChecked = true; } const selectedRows = this.getSelectedRowsObject(rows, displayedRows, selected, trackByProp); return { selectedRows, selected, selectAllChecked, selectAllIndeterminate }; } getSelectAllState(displayedRows: any[], selected: any[], rowSelectionDisabledProp?: string): { checked: boolean, indeterminate: boolean } { let selectAllChecked = false; if (rowSelectionDisabledProp != null) { selectAllChecked = displayedRows.every(x => selected.includes(x) || x[rowSelectionDisabledProp]); } else { selectAllChecked = displayedRows.every(x => selected.includes(x)); } const selectAllIndeterminate = !selectAllChecked && displayedRows.some(x => selected.includes(x)); return { checked: selectAllChecked, indeterminate: selectAllIndeterminate }; } toggleSelectRow(row: any, rows: any[], displayedRows: any, selected: any[], selectedRows: Object, selectAllChecked: boolean, selectAllIndeterminate: boolean, trackByProp: string, selectionType: SelectionType, rowSelectionDisabledProp?: string): TableSelectResults { if (rowSelectionDisabledProp != null && row[rowSelectionDisabledProp] === true) { return { selectedRows, selected, selectAllChecked, selectAllIndeterminate }; } switch (selectionType) { case SelectionType.single: return this.toggleSingleRow(row, rows, displayedRows, selected, trackByProp); default: return this.toggleRow(row, rows, displayedRows, selected, trackByProp, rowSelectionDisabledProp); } } private toggleRow(row: any, rows: any[], displayedRows: any[], selected: any[], trackByProp: string, rowSelectionDisabledProp?: string): TableSelectResults { let rowSelected = false; if (selected != null && selected.some(x => x === row)) { selected.splice(selected.indexOf(row), 1); rowSelected = false; } else { selected.push(row); rowSelected = true; } const selectAllState = this.getSelectAllState(displayedRows, selected, rowSelectionDisabledProp); const selectAllChecked = selectAllState.checked; const selectAllIndeterminate = selectAllState.indeterminate; const selectedRowsObject = this.getSelectedRowsObject(rows, displayedRows, selected, trackByProp); return { selectedRows: selectedRowsObject, selected, selectAllChecked, selectAllIndeterminate }; } private toggleSingleRow(row: any, rows: any[], displayedRows: any[], selected: any[], trackByProp: string): TableSelectResults { if (selected != null && selected.some(x => x[trackByProp] === row[trackByProp])) { selected = []; } else { selected = [row]; } const selectAllChecked = false; const selectAllIndeterminate = false; const selectedRowsObject = this.getSelectedRowsObject(rows, displayedRows, selected, trackByProp); return { selectedRows: selectedRowsObject, selected, selectAllChecked, selectAllIndeterminate }; } }