1

我有带有内联编辑的 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>) { }

}
4

1 回答 1

0

我发现你遇到了我的问题。经过一番调查并查看您的代码后,我们犯了同样的错误。

我们忘记声明所有指令。

declarations: [
    ....
    EditModeDirective,
    EditableOnEnterDirective,
    ViewModeDirective,
    EditableOnClickDirective,
    FocusableDirective
  ],

Angular 中没有任何内容显示该指令已被遗漏。我有点明白为什么。

于 2020-10-22T09:22:20.803 回答