Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular CDK drag drop with (reactive) forms

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>
like image 673
tech-no-logical Avatar asked Nov 08 '18 15:11

tech-no-logical


People also ask

How do you drag and drop CDK?

Start by importing DragDropModule into the NgModule where you want to use drag-and-drop features. You can now add the cdkDrag directive to elements to make them draggable. When outside of a cdkDropList element, draggable elements can be freely moved around the page.

What is FormBuilder in reactive forms?

The FormBuilder service is an injectable provider that is provided with the reactive forms module. We will inject this dependency by adding it to the component constructor. File name : employeeDetails-editor.component.ts. 1constructor(private fb: FormBuilder) { } typescript.

Why do we use FormControl in angular?

Put simply, form controls in Angular give the developer all the control, and nothing is implicit anymore — every choice about inputs and controls must be made intentionally and, of course, explicitly.

Are reactive forms robust?

Reactive forms are more robust: they're more scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms. Template-driven forms are useful for adding a simple form to an app, such as an email list signup form.


1 Answers

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..

like image 66
KimCindy Avatar answered Sep 17 '22 16:09

KimCindy