多行删除的角度可重复使用材料表复选框



我是Angular的初学者。在我的项目中,根据需求,我们为Angular创建了一个可重复使用的材料表组件。在这个表中,我们在各个表行上都有类似"编辑"one_answers"删除"这样的选项
现在,我们收到了在数据表中实现复选框的要求,以便可以选择和删除多行
我们正在使用NGRX进行应用程序状态管理

关于这一点,如果我能得到一些关于如何实施这一点的指导,那将是非常有帮助的

我已尝试在表中添加复选框
但是,我不知道如何在组件级别实现Delete操作

//Data-Table
import { Component, OnInit, Input, Output, EventEmitter, SimpleChanges, OnChanges, ViewChild } from '@angular/core';
import { MatTableDataSource, MatPaginator } from '@angular/material';
import { FormGroup, FormControl, ValidatorFn } from '@angular/forms';
import * as moment from 'moment';
import {SelectionModel} from '@angular/cdk/collections';
export enum ColumnTypes {
ColumnTypeReadonly = 0,
ColumnTypeLink = 1,
ColumnTypeEdit = 2,
ColumnTypeProgress = 3,
ColumnTypeDate = 4,
}
export enum ColumnEditTypes {
EditTypeText = 0,
EditTypeNumeric = 1,
EditTypeBoolean = 3,
EditTypeDate = 4,
}
export interface ColumnDef {
id: string;
text: string;
columnType?: ColumnTypes;
editType?: ColumnEditTypes; // If ColumnType is ColumnTypeEdit
editValidations?: ValidatorFn[];
width?: string;
requiredColumn?: boolean;
hideColumn?: boolean;
}
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.scss']
})
export class DataTableComponent implements OnInit, OnChanges {
showFiller = false;
@Input() loading = false;
@Input() data: any = null;
@Input() displayColumns: ColumnDef[] = [];
@Input() disableEdit: boolean;
@Input() disableDelete: boolean;
@Input() showEdit: boolean;
@Input() showDelete: boolean;
@Input() showPaginator: boolean;
@Input() showHorizontalScroll: boolean;
@Input() hasInlineEditor: boolean;
@Output() dataAction = new EventEmitter();
@Output() linkAction = new EventEmitter();
@Output() highlightRow = new EventEmitter();
//checkbox
@Input() showCheckbox: boolean;
@Output() removeSelected = new EventEmitter();
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
dataSource: MatTableDataSource<any> = null;
columns: ColumnDef[] = [];
columnsIds: string[] = [];
isEditorOpen = false;
inlineEditIndex: number;
inlineEditObj: any;
recordsFormGroup: FormGroup;
highlightedRow: any;
rowWidth = '100%';
//checkbox
selection = new SelectionModel<MatTableDataSource<any>>(true, []);

constructor() { }
ngOnInit() {
this.columns = this.displayColumns.filter((col, idx) => {
if (idx <= 0) {
col.requiredColumn = true;
} else {
col.requiredColumn = false;
}
return !col.hideColumn;
});
this.columnsIds.push('colorCode');
this.columns.map(col => {
this.columnsIds.push(col.id);
});
if (this.showEdit || this.showDelete) {
this.columnsIds.push('action');
}
//Checkbox
if (this.showCheckbox) {
this.columnsIds.push('select');
}
if (this.showHorizontalScroll === true) {
this.displayColumns.forEach(col => {
if (!col.hideColumn) {
// tslint:disable-next-line:radix
this.rowWidth = parseInt(this.rowWidth) + parseInt(col.width) + 'px';
}
});
// tslint:disable-next-line:radix
this.rowWidth = parseInt(this.rowWidth) + 100 + 'px'; // action column
}
}
ngOnChanges(changes: SimpleChanges): void {
this.dataSource = new MatTableDataSource(this.data);
this.createInlineEditForm(this.data);
if (this.showPaginator) {
this.dataSource.paginator = this.paginator;
}
}
createInlineEditForm(recordData: any) {
this.recordsFormGroup = new FormGroup({});
if (recordData) {
recordData.map((record, idx) => {
this.displayColumns.map(column => {
if (column.columnType === ColumnTypes.ColumnTypeEdit) {
const control: FormControl = new FormControl(record[column.id], column.editValidations);
this.recordsFormGroup.addControl(column.id + '-' + idx, control);
}
});
});
}
}
onDataAction($event) {
switch ($event.action) {
case 'edit-action':
this.isEditorOpen = false;
this.inlineEditIndex = -1;
this.dataAction.emit($event);
break;
case 'delete-action':
this.isEditorOpen = false;
this.inlineEditIndex = -1;
this.dataAction.emit($event);
break;
case 'inline-edit-action':
this.isEditorOpen = true;
this.inlineEditIndex = $event.index;
this.inlineEditObj = $event.obj;
break;
case 'inline-delete-action':
this.isEditorOpen = false;
this.inlineEditIndex = -1;
this.dataAction.emit($event);
break;
case 'inline-edit-ok-action':
if (!this.recordsFormGroup.valid) {
return;
}
this.isEditorOpen = false;
this.inlineEditIndex = -1;
this.dataAction.emit({
index: $event.index + (this.paginator.pageIndex * 10),
action: $event.action,
obj: {
originalObj: $event.obj,
formObj: this.createFormDataObj($event.obj, $event.index + (this.paginator.pageIndex * 10))
}
});
break;
case 'inline-edit-cancel-action':
this.resetFormDataObj($event.obj, $event.index + (this.paginator.pageIndex * 10));
this.isEditorOpen = false;
this.inlineEditIndex = -1;
break;
}
}
createFormDataObj(recordData: any, rowIdx: number) {
const formObj = { ...recordData };
this.columns.map((column) => {
if (column.columnType === ColumnTypes.ColumnTypeEdit) {
formObj[column.id] = this.recordsFormGroup.controls[column.id + '-' + rowIdx].value;
}
});
return formObj;
}
resetFormDataObj(recordData: any, rowIdx: number) {
this.columns.map((column) => {
if (column.columnType === ColumnTypes.ColumnTypeEdit) {
this.recordsFormGroup.controls[column.id + '-' + rowIdx].setValue(recordData[column.id]);
}
});
}
onLinkAction(data: any) {
this.linkAction.emit(data);
}
onHighlightRow(data) {
this.highlightedRow = data;
this.highlightRow.emit(data);
}
onPageChange($event) {
if ($event.previousPageIndex !== $event.pageIndex) {
if (this.isEditorOpen) {
this.resetFormDataObj(this.inlineEditObj, this.inlineEditIndex + ($event.previousPageIndex * 10));
this.isEditorOpen = false;
this.inlineEditIndex = -1;
}
}
}
onColumnSelectMenuClick($event, selectedCol: ColumnDef) {
this.displayColumns.map(displayColumn => {
if (displayColumn === selectedCol) {
displayColumn.hideColumn = !displayColumn.hideColumn;
}
return displayColumn;
});
$event.stopPropagation();
return false;
}
displayColumnMenuClosed() {
this.columns = this.displayColumns.filter(col => !col.hideColumn);
this.columnsIds = ['colorCode'];
this.columns.map(col => {
this.columnsIds.push(col.id);
});
if (this.showEdit || this.showDelete) {
this.columnsIds.push('action');
}
}
formatDate(date) {
const dt = moment(date, 'MM-DD-YYYY');
return dt.isValid() ? dt.format('MM-DD-YYYY') : '';
}

//checkbox
isAllSelected() {
const numSelected = this.selection.selected.length;
const numRows = this.dataSource.data.length;
return numSelected === numRows;
}
masterToggle() {
this.isAllSelected() ?
this.selection.clear() :
this.dataSource.data.forEach(row => this.selection.select(row));
}
/* removeSelectedRows() {
this.selection.selected.forEach(item => {
let index: number = this.data.findIndex(d => d === item);
console.log(this.data.findIndex(d => d === item));
this.data.splice(index,1)
this.dataSource = new MatTableDataSource<any>(this.data);
});
this.selection = new SelectionModel<MatTableDataSource<any>>(true, []);
} */
}

//HTML
<div class="mat-elevation-z2">
<ng-container *ngIf="loading === true">
<div class="loading">
<mat-spinner></mat-spinner>
</div>
</ng-container>
<form [formGroup]="recordsFormGroup">
<ng-container *ngIf="loading === false">
<mat-table
#table
[dataSource]="dataSource"
(mouseout)="onHighlightRow(null)"
[ngStyle]="
showHorizontalScroll === true
? { 'overflow-x': 'scroll' }
: { 'overflow-x': 'hide' }
"
>
<ng-container *ngIf="showCheckbox" matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()"
>
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)"
>
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="colorCode">
<mat-header-cell
*matHeaderCellDef
style="max-width: 24px; padding-left: 0px;"
>
</mat-header-cell>
<mat-cell *matCellDef="let element" class="colorCode">
<div
[ngStyle]="
element.recordStatus && element.recordStatus === 'add'
? { 'background-color': 'greenyellow', width: '2px' }
: element.recordStatus === 'edit'
? { 'background-color': 'gold', width: '2px' }
: { 'background-color': 'transparent', width: '2px' }
"
></div>
</mat-cell>
</ng-container>
<ng-container
[matColumnDef]="col.id"
*ngFor="let col of columns; let colIdx = index"
>
<mat-header-cell
class="mat-elevation-z2-table"
*matHeaderCellDef
[ngStyle]="
showHorizontalScroll === true && { flex: '0 0 ' + col.width }
"
>
{{ col.text }}
</mat-header-cell>
<ng-template
[ngIf]="col.columnType === undefined || col.columnType === 0"
>
<!-- Readonly -->
<mat-cell
*matCellDef="let element"
[ngStyle]="
showHorizontalScroll === true && { flex: '0 0 ' + col.width }
"
>
{{ element[col.id] }}
</mat-cell>
</ng-template>
<ng-template [ngIf]="col.columnType === 1">
<!-- Link -->
<mat-cell
*matCellDef="let element"
[ngStyle]="
showHorizontalScroll === true && { flex: '0 0 ' + col.width }
"
>
<b (click)="onLinkAction(element)" style="cursor: pointer;">{{
element[col.id]
}}</b>
</mat-cell>
</ng-template>
<ng-template [ngIf]="col.columnType === 2">
<!-- Inline Edit -->
<mat-cell
*matCellDef="let recordData; let idx = index"
[ngStyle]="
showHorizontalScroll === true && { flex: '0 0 ' + col.width }
"
>
<app-edit-input-wrapper
[isEditorOpen]="isEditorOpen && idx === inlineEditIndex"
[readValue]="recordData[col.id]"
[isValid]="
!recordsFormGroup.controls[
[col.id] + '-' + (idx + paginator.pageIndex * 10)
].invalid
"
>
<ng-template [ngIf]="col.editType === 0">
<input
[formControlName]="
[col.id] + '-' + (idx + paginator.pageIndex * 10)
"
appInputSelectAll
/>
</ng-template>
<ng-template [ngIf]="col.editType === 1">
<input
[formControlName]="
[col.id] + '-' + (idx + paginator.pageIndex * 10)
"
type="number"
appInputSelectAll
appOnlyNumber
/>
</ng-template>
</app-edit-input-wrapper>
</mat-cell>
</ng-template>
<ng-template [ngIf]="col.columnType === 4">
<!-- Date -->
<mat-cell
*matCellDef="let element"
[ngStyle]="
showHorizontalScroll === true && { flex: '0 0 ' + col.width }
"
>
{{ formatDate(element[col.id]) }}
</mat-cell>
</ng-template>
</ng-container>
<ng-container *ngIf="showEdit || showDelete" matColumnDef="action">
<mat-header-cell
*matHeaderCellDef
class="mat-elevation-z2-table"
style="max-width: 100px; display: flex; align-items: center; justify-content: flex-end; padding-right: 0px;"
>
<mat-icon
style="font-size: large; color: red; display: flex; align-items: center; justify-content: flex-end;"
*ngIf="!recordsFormGroup.valid"
>warning</mat-icon
>
<button
mat-button
[matMenuTriggerFor]="menu"
(menuClosed)="displayColumnMenuClosed()"
>
<mat-icon>list</mat-icon>
</button>
<mat-menu #menu="matMenu" yPosition="above">
<div
#menu
mat-menu-item
disableRipple="true"
[disabled]="displayColumn.requiredColumn"
*ngFor="let displayColumn of displayColumns"
(click)="onColumnSelectMenuClick($event, displayColumn)"
>
<mat-checkbox
type="checkbox"
[checked]="!displayColumn.hideColumn"
[disabled]="displayColumn.requiredColumn"
></mat-checkbox>
{{ displayColumn.text }}
</div>
</mat-menu>
</mat-header-cell>
<ng-container>
<mat-cell
*matCellDef="let recordData; let idx = index"
style="max-width: 100px; max-width: 100px; display: flex; align-items: center; justify-content: flex-end; margin-right: -12px;"
>
<app-action-buttons
[disableEdit]="disableEdit"
[disableDelete]="disableDelete"
[showEdit]="showEdit"
[showDelete]="showDelete"
[hasInlineEditor]="hasInlineEditor"
[recordData]="recordData"
[recordIndex]="idx"
[isEditorOpen]="isEditorOpen"
[inlineEditIndex]="inlineEditIndex"
(dataAction)="onDataAction($event)"
>
</app-action-buttons>
</mat-cell>
</ng-container>
</ng-container>
<mat-header-row
*matHeaderRowDef="columnsIds"
[ngStyle]="{ width: rowWidth }"
></mat-header-row>
<mat-row
*matRowDef="let row; columns: columnsIds; let idx = index"
(mouseover)="onHighlightRow(row)"
[ngClass]="
idx == inlineEditIndex
? 'editor'
: row == highlightedRow && 'highlight'
"
[ngStyle]="{ width: rowWidth }"
>
</mat-row>
</mat-table>
</ng-container>
<div [hidden]="!showPaginator || dataSource.data.length <= 10">
<mat-paginator
#paginator
[pageSizeOptions]="[10]"
[disabled]="loading"
showFirstLastButtons
(page)="onPageChange($event)"
></mat-paginator>
</div>
</form>
</div>

在组件中,您触发一个删除事件,类似

@Output() delete= new EventEmitter<any>();
...
onDelete() {
this.delete.emit(data);
}

并且您在超级组件中捕获

<app-action-buttons
[disableEdit]="disableEdit"
[disableDelete]="disableDelete"
[showEdit]="showEdit"
[showDelete]="showDelete"
[hasInlineEditor]="hasInlineEditor"
[recordData]="recordData"
[recordIndex]="idx"
[isEditorOpen]="isEditorOpen"
[inlineEditIndex]="inlineEditIndex"
(dataAction)="onDataAction($event)"
(delete)="onDelete($event)"
>
</app-action-buttons>

最新更新