我有带有内联编辑的 Angular Mat 表。下面的代码内联编辑适用于带有记录的 mat 单元格,但对于具有空值或空记录的单元格内联编辑不起作用。我很乐意让空的 mat 单元格更新和编辑一些价值。任何解决方法都可以满足此要求
表基本示例.html
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column -->
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element;let index = index">
<editable (update)="updateField(index, 'name')">
<ng-template viewMode>
{{element.name}}
</ng-template>
<ng-template editMode>
<mat-form-field class="example-full-width">
<input matInput [formControl]="getControl(index, 'name')">
<mat-error *ngIf="getControl(index, 'name').hasError('required')">
Field is <strong>required</strong>
</mat-error>
</mat-form-field>
<!-- <input [formControl]="getControl(index, 'name')" focusable editableOnEnter> -->
</ng-template>
</editable>
</td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element;let index = index">
<editable (update)="updateField(index, 'weight')">
<ng-template viewMode>
{{element.weight}}
</ng-template>
<ng-template editMode>
<input [formControl]="getControl(index, 'weight')" focusable editableOnEnter>
</ng-template>
</editable>
</td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element;let index = index">
<editable (update)="updateField(index, 'symbol')">
<ng-template viewMode>
{{element.symbol}}
</ng-template>
<ng-template editMode>
<input [formControl]="getControl(index, 'symbol')" focusable editableOnEnter>
</ng-template>
</editable>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
表基本示例.ts
import { Component } from '@angular/core';
import { FormControl, FormArray, FormGroup, Validators } from '@angular/forms';
import {CoreService} from './services/core.service';
/**
* @title Basic use of `<table mat-table>`
*/
@Component({
selector: 'table-basic-example',
styleUrls: ['table-basic-example.css'],
templateUrl: 'table-basic-example.html',
})
export class TableBasicExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = this.core.list$;
controls: FormArray;
constructor(private core: CoreService){}
ngOnInit() {
const toGroups = this.core.list$.value.map(entity => {
return new FormGroup({
position: new FormControl(entity.position, Validators.required),
name: new FormControl(entity.name, Validators.required),
weight: new FormControl(entity.weight, Validators.required),
symbol: new FormControl(entity.symbol, Validators.required)
},{updateOn: "blur"});
});
this.controls = new FormArray(toGroups);
}
updateField(index, field) {
const control = this.getControl(index, field);
if (control.valid) {
this.core.update(index,field,control.value);
}
}
getControl(index, fieldName) {
const a = this.controls.at(index).get(fieldName) as FormControl;
return this.controls.at(index).get(fieldName) as FormControl;
}
}
编辑模式.directive.ts
import { Directive, TemplateRef } from '@angular/core';
@Directive({
selector: '[editMode]'
})
export class EditModeDirective {
constructor(public tpl: TemplateRef<any>) { }
}
可编辑的.component.ts
import { Component, ContentChild, HostListener, ElementRef, EventEmitter, Output, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { ViewModeDirective } from './view-mode.directive';
import { EditModeDirective } from './edit-mode.directive';
import { NgControl } from '@angular/forms';
import { fromEvent, Subject } from 'rxjs';
import { switchMap, takeUntil, filter, take, switchMapTo } from 'rxjs/operators';
import { untilDestroyed } from 'ngx-take-until-destroy';
@Component({
selector: 'editable',
template: `
<ng-container *ngTemplateOutlet="currentView"></ng-container>
`,
styleUrls: ['./editable.component.css']
})
export class EditableComponent {
@ContentChild(ViewModeDirective) viewModeTpl: ViewModeDirective;
@ContentChild(EditModeDirective) editModeTpl: EditModeDirective;
@Output() update = new EventEmitter();
editMode = new Subject();
editMode$ = this.editMode.asObservable();
mode: 'view' | 'edit' = 'view';
constructor(private host: ElementRef) {
}
ngOnInit() {
this.viewModeHandler();
this.editModeHandler();
}
toViewMode() {
this.update.next();
this.mode = 'view';
}
private get element() {
return this.host.nativeElement;
}
private viewModeHandler() {
fromEvent(this.element, 'dblclick').pipe(
untilDestroyed(this)
).subscribe(() => {
this.mode = 'edit';
this.editMode.next(true);
});
}
private editModeHandler() {
const clickOutside$ = fromEvent(document, 'click').pipe(
filter(({ target }) => this.element.contains(target) === false),
take(1)
)
this.editMode$.pipe(
switchMapTo(clickOutside$),
untilDestroyed(this)
).subscribe(event => this.toViewMode());
}
get currentView() {
return this.mode === 'view' ? this.viewModeTpl.tpl : this.editModeTpl.tpl;
}
ngOnDestroy() {
}
}
可编辑的.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { EditableComponent } from './editable.component';
import { ViewModeDirective } from './view-mode.directive';
import { EditModeDirective } from './edit-mode.directive';
import { FocusableDirective } from './focusable.directive';
import { EditableOnEnterDirective } from './edit-on-enter.directive';
import { MaterialModule } from 'app/material/material.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ClickOutsideModule } from 'ng-click-outside';
@NgModule({
declarations: [],
imports: [
CommonModule,
MaterialModule,
FormsModule,
ReactiveFormsModule,
ClickOutsideModule
],
exports: [
]
})
export class EditableModule { }
视图模式.directive.ts
import { Directive, TemplateRef } from '@angular/core';
@Directive({
selector: '[viewMode]'
})
export class ViewModeDirective {
constructor(public tpl: TemplateRef<any>) { }
}