簡體   English   中英

如何使用帶有預定義插槽的 Angular CDK DragDrop?

[英]How to use Angular CDK DragDrop with predefined slots?

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

我有一個項目,我想預測足球聯賽排名。 我有兩個列表,一個用於預測,一個包含所有團隊。

一開始預測列表是空的,所以你可以開始拖入隊伍。但是因為它是空的,所以第一支隊伍自動排名第一。 當然你可以稍后對它們進行排序,但我想要的是基於團隊數量的預定義插槽。 通過這種方式,您可以將團隊直接拖動到正確的位置。

我真的無法在互聯網上找到有關如何實現這一點的解決方案。

這是我目前的情況,所以你可以看到我在說什么: 聯賽預測

這就是我想要實現的目標。 在此處輸入圖片說明

有人知道如何為 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.previousIndex,
                        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')"

在您的 drop 函數中,您可以在列表傳輸的情況下使用此參數來添加或刪除占位符:

  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

好吧,如果沒有有效的 stackblitz,就很難提供任何有用的代碼示例,但我試一試。

對於左側列表,我將創建一個包含與團隊列表大小相同的空對象的數組。

我會創建{name: null, logo: null}條目並檢查模板以if name === null不顯示任何內容

擴展drop事件處理程序並添加檢查if (dropTarget.name === null)並將虛擬條目替換為您的值。 否則保留您現有的邏輯

編輯:基本 Stackblitz 示例: Stackblitz

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM