【问题标题】:Angular 6 - Multi-level nested Reactive Form duplicates inputsAngular 6 - 多级嵌套反应表单重复输入
【发布时间】:2019-02-05 05:24:57
【问题描述】:

我有一个与 Angular Reactive Form 相关的问题,我无法解决。

代码

form.htmlform.ts

import {Component, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {ProcessService} from "../../../service/process.service";


@Component({
  selector: 'app-check-order-form',
  templateUrl: './check-order-form.component.html',
  styleUrls: ['./check-order-form.component.css']
})
export class CheckOrderFormComponent implements OnInit {
  submitted = false;

  X: FormGroup = this._fb.group({
    field: '',
    Y: this._fb.array([])
  });

  Yg: FormGroup = this._fb.group({
    subfield: '',
    Z: this._fb.array([])
  });

  Zg: FormGroup = this._fb.group({
    subsubfield: ''
  });

  constructor(private _fb: FormBuilder) {
  }

  ngOnInit() {
    this.createYg();
    this.createZg();
  }

  ngOnChanges() {
  }

  onSubmit(formValue) {
    this.submitted = true;
    console.warn(this.X.value);
  }

  createYg() {
    return this.Yg;
  }

  createZg() {
    return this.Zg;
  }

  
  get Y(): FormArray {
    return this.X.get('Y') as FormArray;
  }

  getCurrentZ(index): FormArray {
    return this.Y.at(index).get('Z') as FormArray;
  }
  
  addY(): void {
    this.Y.push(this.createYg());
  }

  addZ(index): void {
    let Z = this.Y.at(index).get('Z') as FormArray;
    Z.push(this.createZg());
  }


  deleteY(index) {
    this.Y.removeAt(index);
  }

  deleteZ(Yindex, index) {
    this.getcurrentZ(Yindex).removeAt(index);
  }
}
<form class="form-inline" [formGroup]="X" (ngSubmit)="onSubmit(X.value)">
  
  <div class="form-group col-3 mb-2">
    <label for="field">Field</label>
    <input type="text" class="form-control" formControlName="field" id="field">
  </div>

  <div class="form-inline" formArrayName="Y">
    <div *ngFor="let y of Y?.controls; let k=index">
      <hr/>
      <div [formGroupName]="k" class="row pt-1 pb-1">
        <div class="col-12">
          <label>Y {{k + 1}}</label>
        </div>
        <div class="form-group col-3 mb-2">
          <input type="text" class="form-control" formControlName="subfield" placeholder="subfield">
        </div>
        <div class="form-inline" formArrayName="Z">
          <div *ngFor="let fondo of getCurrentZ(k)?.controls; let j=index">
            <hr class="bg-secondary"/>
            <div [formGroupName]="j" class="pt-1 pb-1">
              <label>Z {{j + 1}}</label>
              <div class="form-group col-3 mb-2">
                <input type="text" class="form-control" formControlName="subsubfield" placeholder="subsubfield">
              </div>        
              <div class="form-group col-3 mb-2">
                <button (click)="deleteZ(k, j)" class="btn btn-danger mr-1">Remove</button>
              </div>
            </div>
          </div>
        </div>        

        <div class="form-group col-12 mb-2 pr-1">
          <button class="btn btn-info mr-1" (click)="addZ(k)">+ Z</button>
        </div>
        <div class="form-group col-12 mb-2 pr-1">
          <button (click)="deleteY(k)" class="btn btn-danger mr-1">
            Remove
          </button>
        </div>
      </div>
    </div>
  </div>

  <div class="form-group col-12 mt-2">
    <button type="submit" class="btn btn-primary mr-2">Submit</button>
    <button (click)="addY()" class="btn btn-success">+ Y</button>
  </div>
</form>

问题

以下是导致问题的步骤(请看一下上面的代码):

  1. 我单击+ Y 按钮以添加 Y FormGroup
  2. 我再次点击+ Y
  3. 我在两个 Y FormGroup 之一上单击 + Z

结果:Z FormGroup 在两个 Y 元素上呈现。

对我来说理想的是每个 FormGroup 只与父级相关,以便正确编译表单。我尝试了许多解决方案,但尽管指定了父数组(Y)的索引,但我找不到问题。

提前谢谢你。

【问题讨论】:

    标签: javascript angular forms nested angular-reactive-forms


    【解决方案1】:

    当您添加Y 表单(和Z 表单)时,您不会创建一个新对象,而是一次又一次地使用同一个对象(YgZg)。因此,当您在 Y 表单上添加“新”Z 时,每个 Y 表单都会受到影响,因为它们是相同的。

    删除 YgZg 并将 createYg()createZg() 替换为:

      createYg() {
        return this._fb.group({
          subfield: '',
          Z: this._fb.array([])
        });
      }
    
      createZg() {
        return this._fb.group({
          subsubfield: ''
        });
      }
    

    【讨论】:

      【解决方案2】:

      请检查代码,我在https://angular-4dt3sa.stackblitz.io 或代码https://stackblitz.com/edit/angular-4dt3sa?file=src%2Fapp%2Fapp.component.ts 中添加了工作模块

      html内容

      <form class="form-inline" [formGroup]="X" (ngSubmit)="onSubmit(X.value)">
      
        <div class="form-group col-3 mb-2">
          <label for="field">Field</label>
          <input type="text" class="form-control" formControlName="field" id="field">
        </div>
      
        <div class="form-inline" formArrayName="Y">
          <div *ngFor="let y of Y?.controls; let k=index">
            <hr/>
            <div> test {{k}}</div>
            <div [formGroupName]="k" class="row pt-1 pb-1">
              <div class="col-12">
                <label>Y {{k + 1}}</label>
              </div>
              <div class="form-group col-3 mb-2">
                <input type="text" class="form-control" formControlName="subfield" placeholder="subfield">
              </div>
              <div class="form-inline" formArrayName="Z">
                <div *ngFor="let fondo of getCurrentZ(k)?.controls; let j=index">
                  <hr class="bg-secondary"/>
                  <div [formGroupName]="j" class="pt-1 pb-1">
                    <label>Z {{j + 1}}</label>
                    <div class="form-group col-3 mb-2">
                      <input type="text" class="form-control" formControlName="subsubfield" placeholder="subsubfield">
                    </div>        
                    <div class="form-group col-3 mb-2">
                      <button (click)="deleteZ(k, j)" class="btn btn-danger mr-1">Remove</button>
                    </div>
                  </div>
                </div>
              </div>        
      
              <div class="form-group col-12 mb-2 pr-1">
                <button class="btn btn-info mr-1" (click)="addZ(k)">+ Z</button>
              </div>
              <div class="form-group col-12 mb-2 pr-1">
                <button (click)="deleteY(k)" class="btn btn-danger mr-1">
                  Remove
                </button>
              </div>
            </div>
          </div>
        </div>
      
        <div class="form-group col-12 mt-2">
          <button type="submit" class="btn btn-primary mr-2">Submit</button>
          <button (click)="addY()" class="btn btn-success">+ Y</button>
        </div>
      </form>
      

      打字稿

      import {Component, OnInit} from '@angular/core';
      import {FormArray, FormBuilder, FormGroup } from '@angular/forms';
      
      @Component({
        selector: 'my-app',
        templateUrl: './app.component.html',
        styleUrls: [ './app.component.css' ]
      })
      export class AppComponent  {
        submitted = false;
      
        X: FormGroup = this._fb.group({
          field: '',
          Y: this._fb.array([])
        });
      
        Yg: FormGroup = this._fb.group({
          subfield: '',
          Z: this._fb.array([])
        });
      
        Zg: FormGroup = this._fb.group({
          subsubfield: ''
        });
      
        constructor(private _fb: FormBuilder) {
        }
      
        ngOnInit() {
          this.createYg();
          this.createZg();
        }
      
        ngOnChanges() {
        }
      
        onSubmit(formValue) {
          this.submitted = true;
          console.warn(this.X.value);
        }
      
        createYg() {
          return this._fb.group({
            subfield: '',
            Z: this._fb.array([])
          });
        }
      
        createZg() {
          return this._fb.group({
            subsubfield: ''
          });
        }
      
      
        get Y(): FormArray {
          return this.X.get('Y') as FormArray;
        }
      
        getCurrentZ(index): FormArray {
          return this.Y.at(index).get('Z') as FormArray;
        }
      
        addY(): void {
          this.Y.push(this.createYg());
        }
      
        addZ(index): void {
          let Z = this.Y.at(index).get('Z') as FormArray;
          let Zg = this.createZg();
          Z.push(Zg);
        }
      
      
        deleteY(index) {
          this.Y.removeAt(index);
        }
      
        deleteZ(Yindex, index) {
          let Z = this.Y.at(Yindex).get('Z') as FormArray;
          Z.removeAt(index);
        }
      }
      

      正如 LP154 所述。您不应该创建新对象。 @teskin

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-04
        • 2019-02-01
        • 2017-03-01
        相关资源
        最近更新 更多