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>
3
  • 1
    An useful post that maybe can solve your problem: No value accessor for form control Commented Feb 15, 2019 at 15:32
  • 1
    If you still need help, could you post your component code as well? Commented Feb 15, 2019 at 16:21
  • Seems like the issue may be related to using formControlName="language" on a <div>. Commented Feb 15, 2019 at 21:01

2 Answers 2

23

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

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.