Angular Drag drop with formArray
Asked Answered
T

2

8

I have 2 arrays. I'm implementing an Angular drag drop and I want to use FormArray to save the array in which the element was dropped into.

The problem is that I can't apply formcontrol to the div as it gives an error

Error: No value accessor for form control with name: 'language'

Here is the 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>
Tragedian answered 15/2, 2019 at 15:20 Comment(3)
An useful post that maybe can solve your problem: No value accessor for form controlWashin
If you still need help, could you post your component code as well?Equinoctial
Seems like the issue may be related to using formControlName="language" on a <div>.Bissau
T
2

Currently we cannot use a formControl with Angular Drag and Drop as it works with div and we cannot add formContol to it. Therefore we need to use the event cdkDropListDropped to update our model manually every time an item has been dropped.

Tragedian answered 21/2, 2019 at 16:3 Comment(0)
W
22

The Angular Material drag / drop API has a moveItemInArray function as seen here

This only supports regular arrays but as per pierNik's answer here on StackOverflow, you can replicate the functionality for a FormArray with the following function:

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);
}

Then in your calling code you pass the formArray in place of a normal array.

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
    );
  }

See working Stackblitz here

Whoa answered 27/8, 2020 at 8:54 Comment(0)
T
2

Currently we cannot use a formControl with Angular Drag and Drop as it works with div and we cannot add formContol to it. Therefore we need to use the event cdkDropListDropped to update our model manually every time an item has been dropped.

Tragedian answered 21/2, 2019 at 16:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.