New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add `moveItemInFormArray()` like materials cdk-drag-drop `moveItemInArray` #27171

Open
ngfelixl opened this Issue Nov 19, 2018 · 3 comments

Comments

Projects
None yet
4 participants
@ngfelixl
Copy link

ngfelixl commented Nov 19, 2018

Hi there,
this is a feature request for a function, e.g. moveItemInFormArray similar to the moveItemInArray function implemented in @angular/material2's cdk drag and drop. I think it is simple and useful, not only for myself, and found some similar posts on SO, so I decided to make a pull request in @angular/material2 for it. But because of the dependency to the FormArray interface, and no cdk dependencies, this might be an interesting feature for the @angular/forms package.

Members of CDK drag and drop event are the previous and the current array item index. Using these one should be able to easily swap the FormArray controls maybe like a standalone function:

import { moveItemInFormArray } from '@angular/forms';
...
moveItemInFormArray(this.formArray, event.previousIndex, event.currentIndex); 

or as a FormArray member function:

this.formArray.moveItem(event.prevousIndex, event.currentIndex);

Do you think this is worth a PR?

@lacolaco

This comment has been minimized.

Copy link
Contributor

lacolaco commented Nov 22, 2018

@ngfelixl Hi. I'm interested in your proposal.
If that API will be out, what do you suppose your application code which using both of CDK DnD and Reactive Forms? I'd like to see the integrated pseudo example code.

@ngfelixl

This comment has been minimized.

Copy link

ngfelixl commented Nov 22, 2018

@lacolaco Sure, see an example I made of DnD and reactive forms here. This implements a similar logic as in this PR but without checking for item existance yet.

The code I use is the following having form: FormGroup({formArray: FormArray}), each FormArray item as item: FormGroup({myControlName: FormControl}). In this example there is no patching for formarrays included, but I think you are able to patch your forms yourself ;)

<form [formGroup]="form">
  <div formArrayName="formArray" class="list" cdkDropList (cdkDropListDropped)="drop($event)">
    <div *ngFor="let control of formArray?.controls; let i = index">
      <button type="button" class="drag-handle" mat-icon-button cdkDragHandle>
        <mat-icon>unfold_more</mat-icon>
      </button>
      <div [formGroupName]="i">
        <input formControlName="myControlName">
      </div>
    </div>
  </div>
</form>

create a getter for your formArray

get formArray(): FormArray {
  return this.form.get('formArray') as FormArray;
}

in the end catch your drop by

drop(event: CdkDragDrop<FormGroup[]>) {
  const dir = event.currentIndex > event.previousIndex ? 1 : -1;

  const from = event.previousIndex;
  const to = event.currentIndex;

  const temp = this.formArray.at(from);
  for (let i = from; i * dir < to * dir; i = i + dir) {
    const current = this.formArray.at(i + dir);
    this.formArray.setControl(i, current);
  }
  this.formArray.setControl(to, temp);
}

but with this PR one could simply do

drop(event: CdkDragDrop<FormGroup[]>) {
  this.formArray.moveItem(event.previousIndex, event.currentIndex);
}

@ngbot ngbot bot added this to the needsTriage milestone Nov 26, 2018

@ngbot ngbot bot modified the milestones: needsTriage, Backlog Nov 27, 2018

@ngfelixl

This comment has been minimized.

Copy link

ngfelixl commented Nov 28, 2018

#27222 is the PR regarding this feature. Thought linking from within the PR text is enough. By the way, is there a local circleci lint test, similar to ./test.sh node/browser/etc? Made some commits which didn't pass linting, and had to commit a fix separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment