Angular 中的嵌套反应式表单:添加到表单数组时会触发 markAsTouched?

问题描述 投票:0回答:2

我目前正在开发一个 Angular 应用程序,涉及创建反应式表单。该表单旨在捕获用户信息以及相关客户的详细信息。主窗体由用户名控件和客户端条目的动态数组组成,可以根据用户输入添加或删除这些条目。

下面是我的组件及其相应的 HTML 模板的片段:

TypeScript - mainForm.component.ts:

export class mainFormComponent implements OnInit {
  mainForm!: FormGroup;

  constructor(
    private fb: FormBuilder,
  ) {}

  ngOnInit(): void {
    this.mainForm = this.fb.group({
      name: ['', [Validators.required]],
      clients: this.fb.array([]),
    });
  }

  get clientForm() {
    return this.adviserForm.get('clients') as FormArray;
  }

  addClient() {
    const client = this.fb.group({
      client_name: ['', [Validators.required]],
    });
    this.clientForm.push(client);
  }

  deleteClient(i: number) {
    this.clientForm.removeAt(i);
  }

  submit() {
    this.mainForm.markAsAllTouched();
  }
}

HTML - main-form.component.html:

<form (ngSubmit)="submit()" [formGroup]="mainForm">
  <input
    [ngClass]="{
      'invalid-input':
        adviserForm.get('name')?.invalid &&
        adviserForm.get('name')?.touched
    }"
    formControlName="adviser_name"
    placeholder="adviser name"
  />
  <hr />
  <h4>Clients</h4>
  <div formArrayName="clients">
    <div
      *ngFor="let client of clientForm.controls; let i = index"
      [formGroupName]="i"
    >
      <input
        [ngClass]="{
          'invalid-input':
            client.get('client_name')?.invalid &&
            client.get('client_name')?.touched
        }"
        formControlName="client_name"
        placeholder="client name"
      />
      <button (click)="deleteClient(i)">Delete Client</button>
    </div>
    <button (click)="addClient()">Add Client</button>
  </div>
  <br />
  <button type="submit">Submit</button>
</form>

主表单具有用户名控件和客户端条目的动态数组。用户可以根据需要添加或删除客户端。为了提供验证反馈,我使用 ngClass 指令应用“invalid-input”类来形成无效且被用户触摸的控件。

我遇到的问题来自 ngClass 的行为,当我单击“添加客户端”时,它会将我的输入元素标记为已触摸。

我的理解是,这与 Angular 的默认更改检测触发我的标记状态有关,我该如何克服这个问题?

javascript angular forms frontend angular-reactive-forms
2个回答
0
投票

我怀疑如果你添加一个必需的 FormControl 来形成默认情况下它会被触摸。

addClient() {
 const client = this.fb.group({
   client_name: ['', [Validators.required]],
 });
 this.clientForm.push(client);
 this.clientForm.markAsPristine();
}

如果您将其标记为原始,这可能会有所帮助。


0
投票

要“到达”FormControl,请使用点符号和 get

mainform.get('clients.'+i+'.client_name')

//or
clientForm.get(i+'.client_name')

顺便说一句,Angular 还向输入添加了 ng-invalid 和 ng-touched 类,请参阅 docs,所以

//instead defined your class invalid-input
.invalid-input{
  color:red;
  border:red;
}
//use
input.ng-invalid.ng-touched{
  color:red;
  border:red;
}

你不需要关心使用[ngClass]

注意:请小心,在您的代码中您使用

adviserForm
但 formGroup 是
mainForm
(我想这是您转录问题时的错误)

© www.soinside.com 2019 - 2024. All rights reserved.