角反应形式的嵌套数组

时间:2020-05-16 23:13:42

标签: javascript html angular typescript angular-reactive-forms

我有一个任务来创建和编辑带有角度的体积。我正在使用反应形式,但是当我尝试编辑它们时,我无法接受卷作者。创建卷时会动态生成它们,但是在“编辑”中看不到它们。我尝试了许多方法,并且在浏览器控制台上看到了各种错误。 这是代码:

  public createMyVolumeForm: FormGroup;

  constructor(private fb: FormBuilder,
              private router: Router,
              private volumeService: VolumeService,
              private route: ActivatedRoute) {
    this.createMyVolumeForm = this.fb.group({
      id: ['', [Validators.required]],
      volumeInfo: this.fb.group({
        title: ['', [Validators.required]],
        authors: this.fb.array([
          this.fb.control('')
        ]),
        publisher: ['', [Validators.required]],
        publishedDate: ['', [Validators.required]],
        pageCount: ['', [Validators.required]],
        imageLinks: this.fb.group({
          thumbnail: ['', [Validators.required]]
        })
      })
    });
  }

  createMyVolume(): void {
    this.volumeService.createMyVolume(this.createMyVolumeForm.value)
      .subscribe(data => {
        this.router.navigateByUrl('my-volumes');
        console.log(this.createMyVolumeForm.value);
      });
  }

  ngOnInit(): void {
    this.route.paramMap.subscribe(params => {
      const volumeId = params.get('id');
      if (volumeId) {
        this.getCurrentVolume(volumeId);
      }
    });
  }

  private getCurrentVolume(id: string): void {
    this.volumeService.getVolume(id).pipe(take(1)).subscribe(
      (volume: IVolume) => this.editVolume(volume)
    );
  }

  private editVolume(volume: IVolume): void {
    this.createMyVolumeForm.patchValue({
      id: volume.id,
      volumeInfo: {
        title: volume.volumeInfo.title,
        publisher: volume.volumeInfo.publisher,
        authors: this.fb.group(this.authors),
        publishedDate: volume.volumeInfo.publishedDate,
        pageCount: volume.volumeInfo.pageCount,
        imageLinks: {
          thumbnail: volume.volumeInfo.imageLinks.thumbnail,
        }
      }
    });
  }

  get authors(): FormArray {
    return this.createMyVolumeForm.get('volumeInfo.authors') as FormArray;
  }

  addMoreAuthors() {
    this.authors.push(this.fb.control(''));
  }
}```

HTML: 
<section class="form-holder">
  <h2 class="form-heading">Create Volume</h2>
  <form [formGroup]='createMyVolumeForm'>
    <div class="input">
      <label class="required-input" for="id">Id</label> <input id="id" type="text" formControlName="id" name="id"/>
    </div>
    <div formGroupName="volumeInfo">
      <div class="input-holder">
        <label class="required-input" for="title">Title</label>
        <div class="input">
          <input id="title" type="text" formControlName="title" name="title"/>
        </div>
        <button type="submit" class="button" (click)="addMoreAuthors()">Add Authors</button>
        <div formArrayName="authors">
          <div *ngFor="let author of authors.controls; let i = index;">
            <label>Authors</label> <input type="text" [formControlName]="i">
          </div>
        </div>
        <label class="required-input" for="publisher">Publisher</label>
        <div class="input">
          <input id="publisher" type="text" formControlName="publisher" name="publisher">
        </div>
        <label class="required-input" for="publishedDate">Published Date</label>
        <div class="input">
          <input id="publishedDate" type="text" formControlName="publishedDate" name="publishedDate">
        </div>
        <label class="required-input" for="pageCount">Page Count</label>
        <div class="input">
          <input id="pageCount" type="number" formControlName="pageCount" name="pageCount">
        </div>
        <div formGroupName="imageLinks">
          <label class="required-input" for="thumbnail">Thumbnail</label>
          <div class="input">
            <input id="thumbnail" type="text" formControlName="thumbnail" name="thumbnail">
          </div>
        </div>
      </div>
      <div class="login-button-holder">
        <input class="login-button"
               type="submit"
               [disabled]="createMyVolumeForm.invalid"
               (click)="createMyVolume()" value="Create"/>
      </div>
    </div>
  </form>
</section>

2 个答案:

答案 0 :(得分:1)

FormArrays有一个令人困惑的API。它们不是表示数组值的FormControl,而是表示FormControls的数组。因此,如果要为表单分配一组作者,每个作者都是可编辑的,则需要为每个作者创建一个新控件,并将其添加到FormArray。

以这个为例:

private editVolume(volume: IVolume): void {
    this.createMyVolumeForm.patchValue({
      id: volume.id,
      volumeInfo: {
        title: volume.volumeInfo.title,
        publisher: volume.volumeInfo.publisher,
        authors: this.fb.group(this.authors),
        publishedDate: volume.volumeInfo.publishedDate,
        pageCount: volume.volumeInfo.pageCount,
        imageLinks: {
          thumbnail: volume.volumeInfo.imageLinks.thumbnail,
        }
      }
    });
  }

一种方法是在其中分配给作者,而改为执行authors: new FormArray([])

然后将值修补到表单中,然后执行以下操作:

(this.createMyVolumeForm.get('authors') as FormArray).clear();
this.authors.forEach(a => {
     const control = new FormControl(a);
     (this.createMyVolumeForm.get('authors') as FormArray).add(control);
});

希望这能使您走上正确的轨道。

答案 1 :(得分:0)

谢谢杰西, 您的答案确实让我在短短的tweek内就走上了正轨:

 showExistingAuthors(volume: IVolume): void {
    (this.createMyVolumeForm.get('volumeInfo.authors') as FormArray).clear();
    volume.volumeInfo.authors.forEach(a => {
      const control = new FormControl(a);
      (this.createMyVolumeForm.get('volumeInfo.authors') as FormArray).push(control);
    });
  }```