Angular CDK drag drop with (reactive) forms
Asked Answered
D

3

6

I have this example : https://stackblitz.com/edit/angular-asevei?file=app%2Fcdk-drag-drop-sorting-example.html

everything works, but while dragging the selectbox 'resets' to the first value in the list.

is there any way to fix this? It's only visual, but quite jarring for the user. I have tried using the cdkDragPreview option, but couldn't get it to work.

Component:

import { Component } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { FormBuilder, FormGroup, FormArray } from '@angular/forms';

@Component({
    selector: 'cdk-drag-drop-sorting-example',
    templateUrl: 'cdk-drag-drop-sorting-example.html',
    styleUrls: ['cdk-drag-drop-sorting-example.css'],
})
export class CdkDragDropSortingExample {

    myForm: FormGroup;

    constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
        title: ['title'],
        items: fb.array([
        fb.group({
            name: fb.control('1'),
            note: fb.control('quux')
        }),
        fb.group({
            name: fb.control('2'),
            note: fb.control('bar')
        }),
        fb.group({
            name: fb.control('3'),
            note: fb.control('baz')
        })

        ])
    })
    }

    drop(event: CdkDragDrop<string[]>) {
    moveItemInArray(this.myForm.get('items').controls, event.previousIndex, event.currentIndex);
    moveItemInArray(this.myForm.get('items').value, event.previousIndex, event.currentIndex);
    }
}

Template:

<form [formGroup]="myForm">
    <input formControlName="title" />
    <div cdkDropList id="foo" class="example-list" (cdkDropListDropped)="drop($event)">
        <div class="example-box" *ngFor="let item of myForm.get('items').controls" cdkDrag>
            <span cdkDragHandle>drag</span>
            <div [formGroup]="item">
                <input type="text" formControlName="name">
                <select formControlName="note">
                    <option>foo</option>
                    <option>bar</option>
                    <option>baz</option>
                    <option>quux</option>
                </select>
            </div>
        </div>
    </div>
    {{ myForm.value | json }}
</form>
Donnydonnybrook answered 8/11, 2018 at 15:12 Comment(1)
how did your drag n drop form project evolve. I'm working on a similar project. Would you like to chat ?Crus
C
8

I have revised @Amir Fawzy's answer by adding a variable in getting the current active note which shows upon dragging the selected box.

TS:

activeNote: string;
enter(i) {
  this.activeNote = this.myForm.get('items')['controls'][i].get('note').value;
}

HTML:

<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
  <div [id]="i" class="example-box" *ngFor="let item of myForm.get('items').controls; let i=index;" cdkDrag #elem="cdkDrag" (mouseenter)="enter(i)">
    <span cdkDragHandle>drag</span>
    <div [formGroup]="item">
      <input type="text" formControlName="name">
      <select formControlName="note">
        <option [hidden]="elem.moved">{{activeNote}}</option>
        <option>foo</option>
        <option>bar</option>
        <option>baz</option>
        <option>quux</option>
      </select>
    </div>
  </div>
</div>

Here's a duplicate on Stackblitz..

Commons answered 9/11, 2018 at 0:19 Comment(3)
both yours and @Amir Fawzy's answers led me to a slighly different solution shown here : stackblitz.com/edit/angular-asevei-wwblpi?file=app/… using the activeNote option with the *cdkDragPreview directive and the (cdkDragStarted) event. thanks !Donnydonnybrook
*cdkDragPreview is another great option. We're just focused on the display at the selectbox. Anyways, glad I could help :)Commons
@Donnydonnybrook I believe you could report this as a bug on the github repo: github.com/angular/material2/issues I wouldn't expect the selects to react this way at all. Im looking into it myself with little luck as to why it's happening. The preview is a nice work around though.Customable
I
0

your code is fine nothing wrong with it but this issue if called it so, caused by drag-drop cdk as this's the default behavior as i know but you can work around to enhance that behavior to make it looks good to the user.

try this

<div class="example-box" *ngFor="let item of myForm.get('items').controls" cdkDrag #elem="cdkDrag">
  <span cdkDragHandle>drag</span>
  <div [formGroup]="item">
    <input type="text" formControlName="name">
    <select formControlName="note">
      <option [hidden]="elem.moved">dragging...</option>
      <option>foo</option>
      <option>bar</option>
      <option>baz</option>
      <option>quux</option>
     </select>
  </div>
</div>

what happened here to things #elem="cdkDrag" added to drag element as local reference
and <option [hidden]="elem.moved">dragging...</option> what gonna happen here is when the user drag the element dragging select option will show in select input when user end the dragging it will hide again and select input value will set again with some css it will looks good.

Incubation answered 8/11, 2018 at 16:26 Comment(0)
P
0

It seems that mat-select from Angular Material works fine, see https://ngfelixl.github.io/ng-libraries

Pummel answered 16/7, 2020 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.