Как использовать Angular7 (угловой материал) перетаскивание между двумя компонентами

Как недавно Angular представил перетаскивание в угловом материале https://material.angular.io/cdk/drag-drop/overview.

Все примеры описаны в одном компоненте. Как использовать это в двух разных компонентах, перетащите один элемент компонента в другой компонент.


person Jomy Joseph    schedule 21.11.2018    source источник


Ответы (5)


Вы можете использовать свойства id и cdkDropListConnectedTo, чтобы связать оба списка:

Компонент 1:

<div cdkDropList id="list-1" cdkDropListConnectedTo="list-2" (cdkDropListDropped)="drop($event)">
    <div *ngFor="let item of list" cdkDrag>{{ item }}</div>
</div>

Компонент 2:

<div cdkDropList id="list-2" cdkDropListConnectedTo="list-1" (cdkDropListDropped)="drop($event)">
  <div *ngFor="let item of list" cdkDrag>{{ item }}</div>
</div>

Если вам нужно объединить несколько списков в один список, вы можете использовать следующий синтаксис: [cdkDropListConnectedTo]="['list-1', 'list-2', 'list-3', 'list-4']"

После связывания списков необходимо правильно обновить один или оба списка в зависимости от действий. Вы можете сделать это с помощью функции перетаскивания следующим образом:

drop(event: CdkDragDrop<string[]>) {
    if (event.container.id === event.previousContainer.id) {
      // move inside same list
      moveItemInArray(this.list, event.previousIndex, event.currentIndex);
    } else {
      // move between lists
    }
}

Для перемещения элементов между списками вы, возможно, захотите централизованно отслеживать списки. Вы можете сделать это, используя Сервис, Магазин или другие методы.

person GCSDC    schedule 22.11.2018
comment
Спасибо. Это подходит для одного блока перетаскивания, если я хочу, чтобы несколько, например [cdkDropListConnectedTo] = [list-2, list-3, list-4], не работали. как добиться этого - person Jomy Joseph; 22.11.2018
comment
@JomyJoseph Я обновил ответ, включив поддержку связи между несколькими списками. Если это решит вашу проблему, примите ответ. Если нет, дайте нам знать. - person GCSDC; 22.11.2018
comment
Конечно. Вы рок. Я пропустил одиночную кавычку для каждого идентификатора. - person Jomy Joseph; 22.11.2018
comment
в angular 7.2.1 мне пришлось использовать [] вокруг cdkDropListConnectedTo, чтобы работать даже с одним списком. [cdkDropListConnectedTo]="[list-1]" или [cdkDropListConnectedTo]="['list-1']" - person deelde; 15.01.2019
comment
@Dirk протестировал его с angular 7.2.0 и angular material / cdk 7.2.1, и он работал с тем же синтаксисом, что и раньше: cdkDropListConnectedTo="list-1" - person GCSDC; 15.01.2019
comment
@GCSDC извините, вы правы. Протестировано прямо сейчас, работает. не знаю, в чем была ошибка вчера. - person deelde; 16.01.2019
comment
Вы спасли мне жизнь, сэр. Примеры Angular не включают id=""-часть, которой мне не хватало. - person Spray'n'Pray; 23.04.2021

Не уверен, что вышеуказанное решение по-прежнему работает с angular 7.2.9 и angular material / cdk 7.3.5

У меня это не сработало, и через некоторое время мне удалось заставить его работать с помощью директивы cdkDropListGroup. Все cdkDropList в cdkDropListGroup будут доступны для перетаскивания элементов. Вам больше не нужно связывать списки перетаскивания со свойством cdkDropListConnectedTo.

<div cdkDropListGroup>
<component1></component1>
<component2></component2>
</div>
person Alty    schedule 20.03.2019
comment
Какова ваша реализация? Не могли бы вы предоставить пример причины, по которой я столкнулся с этой проблемой сейчас, и без connectedTo она не работает. У меня есть компонент со списком, в котором реализовано перетаскивание, и я хочу использовать его в такой группе. - person Adam Michalski; 06.06.2019
comment
Спас день !! - person Jonathan Corrin; 26.07.2019

Вам просто нужно создать метод перетаскивания в службе и вызвать этот метод перетаскивания из двух компонентов. И нужно обернуть эти два компонента cdkDropListGroup на родительский компонент.

Компонент приложения

<div class="wrapper">
  <div cdkDropListGroup>
    <app-test1></app-test1>
    <app-test2></app-test2>
  </div>
</div>

Компонент Test1

<div class="container">
  <h2>Movies</h2>
  <div cdkDropList [cdkDropListData]="MoviesList"
    class="movie-list" (cdkDropListDropped)="onDrop($event)">
    <div class="movie-block" *ngFor="let moviesList of MoviesList" cdkDrag>{{moviesList}}</div>
  </div>
</div>

  export class Test1Component implements OnInit {

  constructor(private ss: ShareService) { }

  ngOnInit() {
  }

  // Transfer Items Between Lists
  MoviesList = [
    'The Far Side of the World',
    'Morituri',
    'Napoleon Dynamite',
    'Pulp Fiction',
    'Blade Runner',
    'Cool Hand Luke',
    'Heat',
    'Juice'    
  ];


  onDrop(event: CdkDragDrop<string[]>) {
    this.ss.drop(event);
  }

}

Компонент Test2

<div class="container">
  <h2>Movies Watched</h2>
  <div cdkDropList [cdkDropListData]="MoviesWatched"
    [cdkDropListConnectedTo]="list-1" class="movie-list" (cdkDropListDropped)="onDrop($event)">
    <div class="movie-block" *ngFor="let moviesWatched of MoviesWatched" cdkDrag>{{moviesWatched}}</div>
  </div>
</div>

import { Component, OnInit } from '@angular/core';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { ShareService } from '../share.service';


@Component({
  selector: 'app-test2',
  templateUrl: './test2.component.html',
  styleUrls: ['./test2.component.css']
})
export class Test2Component implements OnInit {

  constructor(private ss: ShareService) { }

  MoviesWatched = [
   'Transformers'
  ];

  ngOnInit() {
  }

  onDrop(event: CdkDragDrop<string[]>) {
    this.ss.drop(event);
  }

}

ShareService

import { Injectable } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';


@Injectable()
export class ShareService {

  constructor() { }

  public drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      transferArrayItem(event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex);
    }
  }

}

Вот рабочая ссылка

person ideeps    schedule 10.06.2020

Компонент1

<div cdkDropList id="list-1" cdkDropListConnectedTo="list-2" (cdkDropListDropped)="drop($event)">
    <div *ngFor="let item of list" cdkDrag>{{ item }}</div>
</div>

Компонент 2

<div cdkDropList id="list-2" cdkDropListConnectedTo="list-1" (cdkDropListDropped)="drop($event)">
  <div *ngFor="let item of list" cdkDrag>{{ item }}</div>
</div>

общая служба для обоих компонентов

drop(event: CdkDragDrop<string[]>) {
        if (event.previousContainer === event.container) {
            moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
        } else {
            transferArrayItem(event.previousContainer.data,
                event.container.data,
                event.previousIndex,
                event.currentIndex);
        }
    }

Родительский компонент

<div cdkDropListGroup>
<component1></component1>
<component2></component2>
</div>

вызов метода drop из обоих компонентов

drop(event: CdkDragDrop<string[]>) {
      this.sharedService.drop(event);
  }
person sumit singh    schedule 22.08.2019

Чтобы подключиться к множественному списку, используйте код удара при перетаскивании

[cdkDropListConnectedTo]="['element-1', 'element-2', 'element-3', 'element-4']"
person Sumant Singh    schedule 18.11.2020