如何将 cdkDropList 与 Angular FormArray 和 FormGroup 一起使用?

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

我正在尝试将 FormArray 与 cdkDropList 结合使用。但是,一旦我添加相应的 FormGroup,该组中的 cdkDrag 就会停止工作。为简单起见,我在此处删除了任何其他事件,例如按钮的单击事件等。

所以这有效:

<div cdkDropList cdkDropListOrientation="horizontal" style="display: flex;">
  <ng-container *ngFor="let group of formArray.value; let i = index" formArrayName="myFormArray">
    <div cdkDrag>
      <div cdkDragHandle style="padding: 1em; margin: 1em;background: red;">{{i}}</div>
    </div>
  </ng-container>
</div>

这不是:

<div cdkDropList cdkDropListOrientation="horizontal" style="display: flex;">
  <ng-container *ngFor="let group of formArray.value; let i = index" formArrayName="compositeContent">
    <div [formGroupName]="i" cdkDrag>
      <div cdkDragHandle style="padding: 1em; margin: 1em;background: red;">{{i}}</div>
    </div>
  </ng-container>
</div>

这也不是:

<div cdkDropList cdkDropListOrientation="horizontal" style="display: flex;">
  <ng-container *ngFor="let group of formArray.value; let i = index" formArrayName="compositeContent">
    <div cdkDrag>
      <div cdkDragHandle style="padding: 1em; margin: 1em;background: red;">{{i}}</div>
      <div [formGroupName]="i"></div>
    </div>
  </ng-container>
</div>

这是 formArray getter:

get formArray(): FormArray {
  return this.form.controls["formArray"] as FormArray;
}

当从我的 API 将现有数据添加到 FormArray 时,这就是我创建新 formArray 元素的方式:

addElement(data): void {
   this.formArray.insert(this.formArray.length, this.getNewElementFormGroup(data));
}

getNewElementFormGroup(data): FormGroup {
  return new FormGroup({...});
}

这是一个stackblitz。将 [formGroupName]="i" 添加到 cdkDrag div 以重现错误。

angular formarray formgroups angular-cdk-drag-drop
1个回答
0
投票

formArrayName
必须是
*ngFor
上方的顶部元素。

主要问题是,您需要在控件而不是值上运行 for 循环,这解决了问题。

下面的工作示例!

<form [formGroup]="form">
  <div
    cdkDropList
    cdkDropListOrientation="horizontal"
    style="display: flex;"
    (cdkDropListDropped)="drop($event)"
    formArrayName="myFormArray"
  >
    <ng-container
      *ngFor="
        let formGroup of formArray.controls;
        trackBy: trackBy;
        let i = index
      "
    >
      <div cdkDrag [formGroupName]="i">
        <div cdkDragHandle style="padding: 1em; margin: 1em;background: red;">
          {{ formGroup?.controls?.control?.value }}
        </div>
      </div>
    </ng-container>
  </div>
</form>

ts

import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { Component } from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  FormArray,
  FormControl,
  Validators,
} from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  form: FormGroup;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.form = new FormGroup({
      myFormArray: new FormArray([]),
    });
    this.addElement(1);
    this.addElement(2);
    this.addElement(3);
  }
  get formArray(): FormArray {
    return this.form.controls['myFormArray'] as FormArray;
  }
  addElement(data): void {
    this.formArray.insert(
      this.formArray.length,
      this.getNewElementFormGroup(data)
    );
  }

  trackBy(i, item) {
    return item;
  }

  getNewElementFormGroup(data): FormGroup {
    return new FormGroup({
      control: new FormControl(data, []),
    });
  }

  drop(event: CdkDragDrop<string[]>) {
    moveItemInArray(
      this.formArray.controls,
      event.previousIndex,
      event.currentIndex
    );
  }
}

Stackblitz 演示

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