typescript 在带有let index = index的 *ngFor内点击垫子按钮不会React/激发操作

hivapdat  于 2023-02-05  发布在  TypeScript
关注(0)|答案(4)|浏览(142)

我目前正在一个项目中工作,我有一个reactive form array,它将使用*ngIf显示在模板上。我认为这是正常的用例,没有什么特别的。但现在我构建了这样一个

<div *ngFor="let control of form.controls['someArray'].value; let index = index">
  [...]
  <button mat-flat-button color="warn">Delete</button>
</div>
<button mat-flat-button color="primary">Add</button>

Delete按钮对我的点击没有React,但Add按钮有React。由于某种原因,当我删除let index = index时,它再次工作,或者如果我把按钮放在这个*ngFor之外。
我希望你能帮助我。非常感谢。到目前为止还没有找到任何解决办法。
示例:https://stackblitz.com/edit/angular-form-array-example-hq5tud

import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]="form">
      <input type="checkbox" formControlName="published"> Published
      <div *ngIf="form.controls.published.value">

        <h2>Credentials</h2>
        <button (click)="addCreds()">Add</button>

        <div formArrayName="credentials" *ngFor="let creds of form.controls.credentials?.value; let i = index">
          <ng-container [formGroupName]="i">
            <input placeholder="Username" formControlName="username">
            <input placeholder="Password" formControlName="password">
            <button mat-flat-button (click)="buttonClick()"> Test inside </button>
          </ng-container>
        </div>
        <button mat-flat-button (click)="buttonClick()"> Test outside </button>

      </div>
    </form>
  `,
})
export class AppComponent  {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      published: true,
      credentials: this.fb.array([]),
    });
  }

  addCreds() {
    const creds = this.form.controls.credentials as FormArray;
    creds.push(this.fb.group({
      username: '',
      password: '',
    }));
  }

  buttonClick() {
    console.log('Clicked');
  }
}
fdx2calv

fdx2calv2#

最后我在@ashot-aleqsanyan的帮助下找到了解决办法。原因还不清楚。如果有人对这种行为有什么解释,请告诉我们。
解决方案:将. html模板中的form.controls.credentials?.value替换为form.get('credentials').controls就可以了,之后mat-button就可以在*ngFor中工作了。

import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]="form">
      <input type="checkbox" formControlName="published"> Published
      <div *ngIf="form.controls.published.value">

        <h2>Credentials</h2>
        <button (click)="addCreds()">Add</button>

        <div formArrayName="credentials" *ngFor="let creds of form.get('credentials').controls; let i = index">
          <ng-container [formGroupName]="i">
            <input placeholder="Username" formControlName="username">
            <input placeholder="Password" formControlName="password">
            <button mat-flat-button (click)="buttonClick()"> Test inside </button>
          </ng-container>
        </div>
        <button mat-flat-button (click)="buttonClick()"> Test outside </button>

      </div>
    </form>
  `,
})
export class AppComponent  {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      published: true,
      credentials: this.fb.array([]),
    });
  }

  addCreds() {
    const creds = this.form.controls.credentials as FormArray;
    creds.push(this.fb.group({
      username: '',
      password: '',
    }));
  }

  buttonClick() {
    console.log('Clicked');
  }
}
jtw3ybtb

jtw3ybtb3#

我不知道为什么,但正如您所说,当您在按钮<button mat-flat-button> Test outside </button>中使用指令mat-flat-button时,在<ng-container [formGroupName]="i">中没有触发(click)事件
如果您删除mat-flat-button,它将工作:<button (click)="myFunc()"> Test outside </button>
下面是我用https://stackblitz.com/edit/angular-form-array-example-hq5tud测试的代码:

    • 应用程序组件. ts**:
import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]="form">
      <input type="checkbox" formControlName="published"> Published
      <div *ngIf="form.controls.published.value">

        <h2>Credentials</h2>
        <button (click)="addCreds()">Add</button>

        <div formArrayName="credentials" *ngFor="let creds of form.controls.credentials?.value; let i = index">
          <ng-container [formGroupName]="i">
            <input placeholder="Username" formControlName="username">
            <input placeholder="Password" formControlName="password">
            <button class="mat-flat-button" (click)="testFunc()"> Test inside </button>
          </ng-container>
        </div>
        <button mat-flat-button (click)="testFunc()"> Test outside </button>

      </div>
    </form>
  `,
})
export class AppComponent  {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      published: true,
      credentials: this.fb.array([]),
    });
  }

  addCreds() {
    const creds = this.form.controls.credentials as FormArray;
    creds.push(this.fb.group({
      username: '',
      password: '',
    }));
  }

  testFunc() {
    console.log('hello');
  }
}
cngwdvgl

cngwdvgl4#

我终于找到了这背后的原因,mat-button依赖于FocusMoniter,它添加了一个额外的捕获阶段事件侦听器,如果没有提供适当的trackBy,捕获阶段事件将触发ngFor的doDocheck并删除旧元素,添加一个新元素。
put a breakpoint on that ngFor element to see the node be removed
我写了一个article来详细解释这个问题,虽然在我的原因中事件是由overlay添加的事件列表触发的,但是原因是完全相同的。

相关问题