问题描述
我有带内联编辑的Angular Mat-table。内联编辑下面的代码对于具有记录的Mat单元格工作正常,但对于具有空值或空记录的单元格,内联编辑不起作用。我很高兴甚至可以用一些值更新和编辑空的Mat单元。解决该问题的任何方法都会满足此要求
table-basic-example.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>
table-basic-example.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,weight: new FormControl(entity.weight,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;
}
}
edit-mode.directive.ts
import { Directive,TemplateRef } from '@angular/core';
@Directive({
selector: '[editMode]'
})
export class EditModeDirective {
constructor(public tpl: TemplateRef<any>) { }
}
editable.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() {
}
}
editable.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 { }
view-mode.directive.ts
import { Directive,TemplateRef } from '@angular/core';
@Directive({
selector: '[viewmode]'
})
export class viewmodeDirective {
constructor(public tpl: TemplateRef<any>) { }
}
解决方法
我发现您遇到了我的问题。经过一番调查并查看您的代码,我们犯了同样的错误。
我们忘记了声明所有指令。
declarations: [
....
EditModeDirective,EditableOnEnterDirective,ViewModeDirective,EditableOnClickDirective,FocusableDirective
],
在Angular中什么也没有显示该指令已被遗漏。我有点明白为什么。