如何使用 ngx-dnd 在 FormArray 中拖放?

How do I use drag and drop in FormArray with ngx-dnd?

我想在 Angular 中使用 FormArray 5.

我已经用 FormArray 创建了一个表单列表,我想用 ngx-dnd 重新组织它们。

这是我的代码:

<div class="ngx-dnd-container" ngxDroppable [model]="formData.controls">
     <div class="ngx-dnd-item" ngxDraggable [model]="line" formArrayName="lines" *ngFor="let line of formData.controls; let i = index;">
         <div [formGroupName]="i"> 
            <textarea formControlName="linedescription"></textarea>
        </div>
    </div>
</div>

如果用户在拖放后输入文本区域,此代码可以正常工作。

如果用户只是拖放,此代码将不起作用,在这种情况下,我的表单数组 "lines" 与拖放更改顺序之前相同。

我应该如何将 ng-dnd 与 FormArray 一起使用,我可以在我的组件中使用 ng-dnd 的回调方法在 "drop" 之后执行某些操作吗?

好的,我有办法了!

1 - ngx-dnd 事件

ngx-dnd 库允许我们使用许多事件:drop()drag()over()out()remove()cancel(). (Source)

因此,如果项目是 "dropped",您可以在组件中调用自己的方法。例如:

form.component.html

<div (drop)="dropped($event)" 
     class="ngx-dnd-container" 
     ngxDroppable 
     [model]="formData.controls">
//...

form.component.ts

dropped(event) {
    alert('Ok drop is Done !')
}

2 - 更新 FormArray

问题出在这里:我们的 "drop action" 没有重新排序 FormArray。

Angular的FormArray class给出了很多解决这个问题的方法。我选择了 reset() 方法,因为我们可以传递一个值作为参数并更新整个 FormArray。

reset(value?: any, options?: Object)

最后,在 form.component.ts

中更新您的方法
dropped(event) {
    let linesCopy = [];
    this.lines = this.form.get('lines') as FormArray;
    for(let line of this.lines.controls) {
        linesCopy.push(line.value);
    }
    this.lines.reset(linesCopy);
}

它现在可以正常工作了,你可以在这个 Stackblitz.

中看到完整的工作示例和源代码

PS:在 Angular 中操作表单时,请注意仅使用表单 class 方法。不要使用 JavaScript 方法来推送、删除、设置值等。仅使用 FormArray class 方法。