I am trying to combine this example (A dropdown selection that creates mat-chips of selected values) with a drag and drop functionality borrowed from Angular Material's Mat-Chip examples (second example from the top) but for some reason the drag and drop doesn't work. I can drag a chip and when hovering it over another chip it seems to change index but when I drop it (release mouse button) it goes back to it's original place. Is this a compatibility issue with the Material components? This is my code currently:
HTML:
<mat-form-field class="field">
<mat-label>Choose values</mat-label>
<mat-select [formControl]="toppingsControl" multiple>
<mat-select-trigger>
<mat-chip-list
cdkDropList
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="drop($event)"
>
<mat-chip
cdkDrag
*ngFor="let topping of toppingsControl.value"
[removable]="true"
(removed)="onToppingRemoved(topping)"
>
{{ topping.name }}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</mat-select-trigger>
<mat-option *ngFor="let topping of toppings" [value]="topping">{{
topping.name
}}</mat-option>
</mat-select>
</mat-form-field>
Typescript:
import { Component } from "@angular/core";
import {FormControl} from '@angular/forms';
import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop";
export interface Topping {
name: string;
}
@Component({
selector: 'app-control',
templateUrl: 'control.component.html',
styleUrls: ['control.component.scss'],
})
export class ControlComponent {
toppingsControl = new FormControl([]);
toppings: Topping[] = [
{name: 'Value_0'},
{name: 'Value_1'},
{name: 'Value_2'},
{name: 'Value_3'},
{name: 'Value_4'}
];
onToppingRemoved(topping: string) {
const toppings = this.toppingsControl.value as string[];
this.removeFirst(toppings, topping);
this.toppingsControl.setValue(toppings); // To trigger change detection
}
private removeFirst<T>(array: T[], toRemove: T): void {
const index = array.indexOf(toRemove);
if (index !== -1) {
array.splice(index, 1);
}
}
drop(event: CdkDragDrop<Topping[]>) {
moveItemInArray(this.toppings, event.previousIndex, event.currentIndex);
}}
CodePudding user response:
I reproduced your example, saw one mistake
Mistake 1: When you are dragging(here drop
function) the Chips only changes occurs in the array parameter but not the formcontroller parameter. If you change the position of controllers then you will get whats required. ie,
drop(event: CdkDragDrop<Topping[]>) {
moveItemInArray(this.toppings, event.previousIndex, event.currentIndex);
}}
becomes
drop(event: CdkDragDrop<Topping[]>) {
moveItemInArray(this.toppings, event.previousIndex, event.currentIndex);
moveItemInArray(this.toppingsControl.value, event.previousIndex, event.currentIndex);
}
Hope this will clear your doubts. For further reference go through multi-test
of the below example. Here you can do the comparison with the original examples(that you provided).