如何在预定义的插槽中使用Angular CDK DragDrop?

问题描述

StackBlitz:https://stackblitz.com/edit/league-predictions

我有一个项目要预测足球联赛的排名。我有两个列表,一个用于预测,另一个用于所有团队。

开始时,预测列表为空,因此您可以开始将团队拖入其中。但是由于该列表为空,因此自动将第一个团队排在第一位。当然您可以稍后对其进行排序,但是我想要的是基于团队数量的预定义插槽。这样,您可以将团队直接拖到正确的位置。

在Internet上我真的找不到解决方案。

这是我目前的情况,因此您可以了解我在说什么: League Predictions

这就是我要实现的目标。

enter image description here

有人知道如何预定义Angular CDK DragDrop的插槽

这是我当前的代码

<div class="container">
  <div class="example-container">
    <h5>Predictions</h5>
    
    <div
      cdkDropList
      #predictionsList="cdkDropList"
      [cdkDropListData]="predictions"
      [cdkDropListConnectedTo]="[teamList]"
      class="example-list"
      (cdkDropListDropped)="drop($event)"
    >
  
      <div class="example-Box" *ngFor="let prediction of predictions; let i = index" cdkDrag>
        <app-team [team]="prediction" [index]="i"></app-team>
      </div>
  
    </div>
  </div>
  
  <div class="example-container">
    <h5>Teams</h5>
  
    <div
      cdkDropList
      #teamList="cdkDropList"
      [cdkDropListData]="teams"
      [cdkDropListConnectedTo]="[predictionsList]"
      class="example-list"
      (cdkDropListDropped)="drop($event)"
    >
  
    <div class="example-Box" *ngFor="let team of teams;" cdkDrag>
      <app-team [team]="team"></app-team>
    </div>
  
    </div>
  </div>
</div>

不用管很长的团队,这全都是数据库中的数据

import { Component,OnInit,ElementRef,ViewChild } from '@angular/core';
import { CdkDragDrop,moveItemInArray,transferArrayItem } from '@angular/cdk/drag-drop';

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

  ngOnInit(): void {
  }

  predictions = [
  ];

  teams = [
    {
      name: 'ADO Den Haag',logo: 'Ado-Den-Haag-logo.png'
    },{
      name: 'Ajax',logo: 'AFC-Ajax-logo.png'
    },{
      name: 'AZ',logo: 'AZ-Alkmaar-logo.png'
    },{
      name: 'FC emmen',logo: 'FC-emmen-logo.png'
    },{
      name: 'FC Groningen',logo: 'FC-Groningen-logo.png'
    },{
      name: 'FC Twente',logo: 'fc-twente-logo.png'
    },{
      name: 'FC Utrecht',logo: 'FC-Utrecht-logo.png'
    },{
      name: 'Feyenoord',logo: 'Feyenoord-Rotterdam-logo.png'
    },{
      name: 'Fortuna Sittard',logo: 'Fortuna-Sittard-logo.png'
    },{
      name: 'Heracles',logo: 'Heracles-Almelo-logo.png'
    },{
      name: 'PEC Zwolle',logo: 'PEC-Zwolle-logo.png'
    },{
      name: 'PSV',logo: 'PSV-Eindhoven-logo.png'
    },{
      name: 'RKC Waalwijk',logo: 'rkc-waalwijk.png'
    },{
      name: 'SC Heerenveen',logo: 'SC-Heerenveen-logo.png'
    },{
      name: 'Sparta Rotterdam',logo: 'Sparta_Rotterdam_logo.png'
    },{
      name: 'Vitesse',logo: 'Vitesse-Arnhem-logo.png'
    },{
      name: 'VVV Venlo',logo: 'VVV-Venlo-logo.png'
    },{
      name: 'Willem II',logo: 'Willem-II-logo.png'
    },];

  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.currentIndex);
    }
  }

}

解决方法

进行了概述,首先要在预测数组中创建虚拟条目:

  getPrediction(): Team[] {
    let localStorageItem = JSON.parse(localStorage.getItem(this.league.name));
    return localStorageItem == null ? this.getTeams().map(t => ({})) : localStorageItem.standings;
  }

这将填写您的位置。禁用在这些项目上拖动:

<div class="example-box" *ngFor="let prediction of predictions; let i = index" cdkDrag [cdkDragDisabled]="!prediction.name">

接下来,您需要在drop函数中添加一个参数,以了解要放到哪个容器上:

drop(event: CdkDragDrop<Team[]>,droppedOn: 'teams' | 'predictions') {

并适当更新模板:

(cdkDropListDropped)="drop($event,'predictions')"

 ...

(cdkDropListDropped)="drop($event,'teams')"

在放置函数中,如果要进行列表传输,则可以使用此参数来添加或删除占位符:

  if (droppedOn === 'teams') {
    // moved back to teams,need to re add placeholder
    this.predictions.push({});
  } else {
    // otherwise,removing a placeholder
    // find the idx to remove,first placeholder at or below current idx
    let removeIdx = this.predictions.findIndex((t,i) => i >= event.currentIndex && !t.name);
    if (removeIdx < 0) {
      // or just the first available.
      removeIdx = this.predictions.findIndex(t => !t.name);
    }
    this.predictions.splice(removeIdx,1);
  }
  transferArrayItem(event.previousContainer.data,event.container.data,event.previousIndex,event.currentIndex);

也许可以对算法进行一些调整/改进,以确定在将团队放到团队中的情况下要删除哪个空白,或者在切换回团队的位置插入空白的位置,但是这里的简单版本效果很好当我玩的时候。

闪电战:https://stackblitz.com/edit/league-predictions-ouu8nr?file=src%2Fapp%2Fprediction%2Fprediction.component.ts

,

如果没有有效的堆栈闪电,很难提供任何有用的代码样本,但是我给了它一个机会。

对于左侧列表,我将创建一个包含空对象的数组,其大小与您的团队列表相同。

我将创建{name: null,logo: null}条目并在模板中进行检查以不显示任何内容if name === null

扩展drop事件处理程序,并添加一个检查if (dropTarget.name === null),并将伪条目替换为您的值。否则请保留现有逻辑

编辑:基本的Stackblitz示例:Stackblitz

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...