formArray 中的可拖动 formGroups(反应式表单)
Posted
技术标签:
【中文标题】formArray 中的可拖动 formGroups(反应式表单)【英文标题】:Draggable formGroups in formArray (reactive forms) 【发布时间】:2019-10-02 14:30:59 【问题描述】:在角度拖放模块中,他们提供了 moveItemInArray() 函数的文档,通过使用这个我们只能拖动数组中的内容。但是,我们如何在 formArray 中打乱(formGroups/formControls)?
即使我尝试了这个 moveItemInFormArray() 函数,正如这里提到的 https://github.com/angular/angular/issues/27171。但我不能让它工作。
groupDrag.component.html
<form [formGroup]="exampleForm">
<div formArrayName="formUnits" cdkDropList (cdkDropListDropped)="drop($event)" *ngFor="let unit of exampleForm.controls.formUnits.controls; let i=index" class="rowGroup">
<div [formGroupName]="i" class="basic-container" cdkDrag>
<div class="row row-container" >
<button type="button" class="drag-handle" mat-icon-button cdkDragHandle>
<mat-icon>unfold_more</mat-icon>
</button>
<!-- label input field -->
<mat-form-field class="col-lg-4">
<input matInput placeholder="Please enter label without spaces" formControlName="label" required>
</mat-form-field>
<!-- options input field -->
<mat-form-field class="col-lg-3">
<input matInput placeholder="Enter Placeholdertext" formControlName="placeholder">
</mat-form-field>
</div>
</div>
</div>
</form>
groupDrag.component.ts
drop(event: CdkDragDrop<FormGroup[]>)
console.log('drop event triggers')
this.formArray = this.exampleForm.get('formUnits') as FormArray;
const from = event.previousIndex;
const to = event.currentIndex;
this.moveItemInFormArray(this.formArray, from, to)
/**
* Moves an item in a FormArray to another position.
* @param formArray FormArray instance in which to move the item.
* @param fromIndex Starting index of the item.
* @param toIndex Index to which he item should be moved.
*/
moveItemInFormArray(formArray: FormArray, fromIndex: number, toIndex: number): void
const from = this.clamp(fromIndex, formArray.length - 1);
const to = this.clamp(toIndex, formArray.length - 1);
if (from === to)
return;
const delta = from > to ? 1 : -1;
for (let i = from; i * delta < to * delta; i += delta)
const previous = formArray.at(i);
const current = formArray.at(i + delta);
formArray.setControl(i, current);
formArray.setControl(i + delta, previous);
/** Clamps a number between zero and a maximum. */
clamp(value: number, max: number): number
return Math.max(0, Math.min(max, value));
【问题讨论】:
【参考方案1】:这是工作示例:
groupDrag.component.ts
import moveItemInFormArray from "./move-item-in-form-array";
drop(event: CdkDragDrop<string[]>)
moveItemInFormArray(this.arrayControls, event.previousIndex, event.currentIndex);
move-item-in-form-array.ts
import FormArray from '@angular/forms';
/**
* Moves an item in a FormArray to another position.
* @param formArray FormArray instance in which to move the item.
* @param fromIndex Starting index of the item.
* @param toIndex Index to which he item should be moved.
*/
export function moveItemInFormArray(formArray: FormArray, fromIndex: number, toIndex: number): void
const dir = toIndex > fromIndex ? 1 : -1;
const from = fromIndex;
const to = toIndex;
const temp = formArray.at(from);
for (let i = from; i * dir < to * dir; i = i + dir)
const current = formArray.at(i + dir);
formArray.setControl(i, current);
formArray.setControl(to, temp);
【讨论】:
this.arrayControls 必须更新为您的数组,但非常感谢!【参考方案2】:这是我的工作解决方案
在component.html中
<form [formGroup]="exampleForm">
<div cdkDropList (cdkDropListDropped)="drop($event)">
<div formArrayName="formUnits" class="rowGroup"
*ngFor="let unit of exampleForm.controls.formUnits.controls; let i=index"
cdkDrag>
<div [formGroupName]="i" class="basic-container" cdkDrag>
<div class="row row-container" >
<button type="button" class="drag-handle" mat-icon-button cdkDragHandle>
<mat-icon>unfold_more</mat-icon>
</button>
<!-- label input field -->
<mat-form-field class="col-lg-4">
<input matInput placeholder="Please enter label without spaces"
formControlName="label" required>
</mat-form-field>
<!-- options input field -->
<mat-form-field class="col-lg-3">
<input matInput placeholder="Enter Placeholdertext" formControlName="placeholder">
</mat-form-field>
</div>
</div>
</div>
</div>
</form>
在component.ts文件中
drop(event: CdkDragDrop<string[]>)
this.formArray = this.exampleForm.get('formUnits') as FormArray;
const from = event.previousIndex;
const to = event.currentIndex;
this.moveItemInFormArray(this.formArray, from, to);
/**
* Moves an item in a FormArray to another position.
* @param formArray FormArray instance in which to move the item.
* @param fromIndex Starting index of the item.
* @param toIndex Index to which he item should be moved.
*/
moveItemInFormArray(formArray: FormArray, fromIndex: number, toIndex: number): void
const from = this.clamp(fromIndex, formArray.length - 1);
const to = this.clamp(toIndex, formArray.length - 1);
if (from === to)
return;
const previous = formArray.at(from);
const current = formArray.at(to);
formArray.setControl(to, previous);
formArray.setControl(from, current);
/** Clamps a number between zero and a maximum. */
clamp(value: number, max: number): number
return Math.max(0, Math.min(max, value));
【讨论】:
作为参考,这个链接很有用。在 AngularInDepth link.medium.com/ONGISEADi5 中使用 tim_deschryver 的新 Angular Material CDK 探索拖放 在我的情况下,我从 中删除了“cdkDrag”以解决索引问题以上是关于formArray 中的可拖动 formGroups(反应式表单)的主要内容,如果未能解决你的问题,请参考以下文章
FormArray 和 formGroup 中的 Angular Material mat-select
剑道:将顶部的 FormGroup 插入 FormArray