Угловое перетаскивание с помощью формы Array
У меня есть 2 массива. Я реализую перетаскивание Angular и хочу использовать FormArray для сохранения массива, в который был вставлен элемент.
Проблема в том, что я не могу применить formcontrol к div, так как он выдает ошибку
Ошибка: нет доступа к значению для управления формой с именем: 'language'
Вот HTML
<div>
<div class="example-container">
<h2>Selected Languages</h2>
<div
cdkDropList
#todoList="cdkDropList"
[cdkDropListData]="anotherarray"
[cdkDropListConnectedTo]="[doneList]"
class="example-list"
(cdkDropListDropped)="drop($event)"
formControlName="language">
<div class="list-group-item list-group-item-action " *ngFor="let item of anotherarray" cdkDrag>
{{item}}
</div>
</div>
</div>
<div class="example-container">
<h2>Available Languages</h2>
<div
cdkDropList
#doneList="cdkDropList"
[cdkDropListData]="testingarray"
[cdkDropListConnectedTo]="[todoList]"
class="example-list"
(cdkDropListDropped)="drop($event)">
<div class="list-group-item list-group-item-action " *ngFor="let item of testingarray" cdkDrag>{{item}}</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary my-2" translate>saveButtonLabel
<fa-icon *ngIf="saveIcon" [icon]="saveIcon" [spin]="saveIcon.iconName === 'spinner'"></fa-icon>
</button>
</form>
1 ответ
В API перетаскивания Angular Material есть функция moveItemInArray, как показано здесь.
Это поддерживает только обычные массивы, но, согласно ответу pierNik здесь, на Stackru, вы можете реплицировать функциональность FormArray с помощью следующей функции:
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 item = formArray.at(fromIndex);
for (let i = fromIndex; i * dir < toIndex * dir; i = i + dir) {
const current = formArray.at(i + dir);
formArray.setControl(i, current);
}
formArray.setControl(toIndex, item);
}
Затем в вызывающем коде вы передаете formArray вместо обычного массива.
get formControls(): FormArray {
return this.form.get('arrayName') as FormArray;
}
constructor() {
this.form = this.formBuilder.group({
arrayName: this.formBuilder.array([]),
});
}
drop(event: CdkDragDrop<string[]>) {
moveItemInFormArray(
this.formControls,
event.previousIndex,
event.currentIndex
);
}
См. Рабочий Stackblitz здесь
В настоящее время мы не можем использовать formControl с Angular Drag and Drop, так как он работает с div, и мы не можем добавить к нему formContol. Поэтому нам нужно использовать событие cdkDropListDropped, чтобы обновлять нашу модель вручную каждый раз, когда элемент был отброшен.