Angular 拖放问题

Trouble with Angular Drag and Drop

我正在尝试让用户拥有一个可以查看公司名片的页面。我希望能够创建容器或只是一些他们可以用来组织它们的排序对象。 我创建了一个我希望它基于的 ng-expansion 面板。但是,我无法在它们之间进行适当的拖放操作。 我一直在使用 cdkDragDrop 工具,我只设法将公司名片本身拖放到屏幕上而不是容器上。我似乎无法建立正确的连接,Angular 网站 cdk 页面似乎只想拖放句子,我找不到重新处理它以拖放我的卡片的方法.

我的扩展面板是这样写的:

    <mat-expansion-panel cdkDropList (opened)="panelOpenState = true" (closed)="panelOpenState = false" (cdkDropListDropped)="drop($event)">
        <mat-expansion-panel-header>
            <mat-panel-title>
                Group Name
            </mat-panel-title>
            <mat-panel-description>
                Currently I am {{panelOpenState ? 'open' : 'closed'}}
            </mat-panel-description>
        </mat-expansion-panel-header>
    </mat-expansion-panel>

我的卡片已格式化为我在此处调用拖放的位置:

<div cdkDropList class="d-flex align-content-start flex-wrap mt-4" (cdkDropListDropped)="drop($event)" *ngIf="!isLoading">
            <ng-container *ngFor="let perspective of watchlist">
                <div class="watchlist-card" cdkDrag>
                    <div class="watchlist-card-content">
                        <div class="d-flex flex-column watchlist-card-body">
                            <!-- CARD HEADER AND REMOVE ICON -->
                            <div class="d-flex flex-row justify-content-between">
                                <p class="card-title">{{ perspective.company.title }}</p>
                                <button class="button-icon" (click)="removeCompanyFromWatchlist(perspective)">
                                    <mat-icon class="btn-close">close</mat-icon>
                                </button>
                            </div>

                            <!-- 3P-SCORE -->
                            <ng-container *ngIf="scoreExists(perspective.company.scores) === true">
                                <div class="d-flex flex-column">
                                    <!-- 3P SCORE HEADER -->
                                    <div class="d-flex flex-row justify-content-between">
                                        <p class="text-header">3P Score</p>
                                        <!-- TOTAL 3P SCORE -->
                                        <p class="text-header"> {{ calculateTotal3PScore(perspective.company.scores)}}/100</p>
                                    </div>
                                    <!-- SCORE BREAKDOWN: People, Product & Performance -->
                                    <ng-container *ngFor="let criteria of scoreCriteria">
                                        <div class="d-flex flex-column">
                                            <!-- SCORE CRITERIA & SCORE OUT OF 100 -->
                                            <div class="d-flex flex-row justify-content-between">
                                                <div class="d-flex flex-row jutify-content-start align-self-center">
                                                    <img src={{criteria.icon}} class="score-icon">
                                                    <p class="score-label align-self-center">{{criteria.label | titlecase}}</p>
                                                </div>
                                                <p class="score-label">{{ perspective.company.scores[0][criteria.label] }}/100
                                                </p>
                                            </div>
                                            <!-- PROGRESS BAR FOR CRITERIA -->
                                            <div class="d-flex flex-row jutify-content-start slider-bottom">
                                                <div class="slider-top"
                                                    [ngStyle]="{width: perspective.company.scores[0][criteria.label]+ '%'}">
                                                </div>
                                            </div>
                                        </div>
                                    </ng-container>
                                </div>
                            </ng-container>

                            <!-- NO 3P SCORE EXISTS -->
                            <ng-container *ngIf="scoreExists(perspective.company.scores) === false">
                                <div class="d-flex flex-column">
                                    <p class="text-header">3P Score</p>
                                    <p class="text-body">We don't have the 3P score of this input as of now. You can request the
                                        score and we will get back to you if it’s a
                                        company.</p>
                                    <button class="btn port-btn small-label" *ngIf="!perspective.company.score_requested"
                                        (click)="request3PScore(perspective)">Request 3P Score</button>
                                    <p class="text-body port-orange" *ngIf="perspective.company.score_requested"><b>Your request
                                            has been registered. We'll get back you to shortly.</b></p>
                                </div>
                            </ng-container>
    
                            <!-- FOOTER: KEWORDS AND ADD BUTTON -->
                            <div class="d-flex flex-column mt-auto">
                                <!-- KEYWORD CHIPS -->
                                <div class="d-flex flex-nowrap watchlist-keywords mt-2 mb-1">
                                    <mat-chip *ngFor="let keyword of perspective.keywords" class="keyword-chip mr-2" [removable]="removable"
                                        (removed)="removeKeywordFromWatchlist(perspective.keywords, keyword, perspective.id)">
                                        {{ keyword }}
                                        <mat-icon matChipRemove *ngIf="removable">close</mat-icon>
                                    </mat-chip>
                                </div>
                                <!-- ADD KEYWORD BUTTON -->
                                <div class="d-flex flex-row flex-fill mr-auto mt-auto">
                                    <!-- INPUT FIELD FOR ADDING KEYWORDS -->
                                    <div class="d-flex flex-row flex-fill justify-content-between align-items-center" *ngIf="perspective.activeAddKeyword">
                                        <div class="d-flex flex-row justify-content-between align-items-center search-bar p-3">
                                            <input [(ngModel)]="keywordInput" type="text" placeholder="Add keyword here" 
                                                (keyup.enter)="addKeywordToWatchlist(perspective.keywords, perspective.id)">
                                            <mat-icon matSuffix type="submit" (click)="addKeywordToWatchlist(perspective.keywords, perspective.id)">add</mat-icon>
                                        </div>
                                        <button class="button-curved ml-2 p-1" *ngIf="perspective.activeAddKeyword"
                                            (click)="closeAddKeywordInput(perspective)">
                                            Cancel
                                        </button>
                                    </div>

                                    <button class="button-icon button-raised mt-auto" *ngIf="!perspective.activeAddKeyword" (click)="showAddKeywordInput(perspective)">
                                        <mat-icon>add</mat-icon>
                                    </button>
                                </div>
                                <div class="card-handle" cdkDragHandle>
                                    <svg width="24px" fill="currentColor" viewBox="0 0 24 24">
                                        <path
                                            d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z">
                                        </path>
                                        <path d="M0 0h24v24H0z" fill="none"></path>
                                    </svg>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </ng-container>
        </div>

其余的卡设置如下,这就是我只是cdkDrag

*编辑,按照其中一个答案的建议修复了 cdkDropList。 *Edit2, 显示了整个卡片代码。

angular material 拖放操作使用列表的概念。 您可以做的是连接列表(拖放,或在同一列表内,或到另一个列表)。

所以,让我们假设扩展面板是一个列表(它是一个列表,因为如果你可以将东西拖到那里,对于 Angular Material 拖放它是一个列表)

将您的扩展面板与不在其中的卡连接。您将拥有并保留两个数组。第一个包含您所有的卡片,第二个包含扩展面板内的卡片

在您的扩展面板中:

<mat-expansion-panel
         cdkDropList
         #expansionPanelList="cdkDropList"
         [cdkDropListData]="arrayCardsInsideExpansion"
         [cdkDropListConnectedTo]="[listOfAllCards]"
         (cdkDropListDropped)="drop($event)"
         (opened)="panelOpenState = true" 
         (closed)="panelOpenState = false">
    <mat-expansion-panel-header>
        <mat-panel-title>
            Group Name
        </mat-panel-title>
        <mat-panel-description>
            Currently I am {{panelOpenState ? 'open' : 'closed'}}
        </mat-panel-description>
    </mat-expansion-panel-header>

    <ng-container *ngFor="let perspective of arrayCardsInsideExpansion">
        <div class="watchlist-card" cdkDrag>
                   .
                   .
                   .
        </div>
    </ng-container>
</mat-expansion-panel>

还有你的牌:

<div cdkDropList 
     #listOfAllCards="cdkDropList"
     [cdkDropListData]="watchlist"
     [cdkDropListConnectedTo]="[expansionPanelList]"
     class="d-flex align-content-start flex-wrap mt-4" 
     (cdkDropListDropped)="drop($event)">
            <ng-container *ngFor="let perspective of watchlist">
                <div class="watchlist-card" cdkDrag>
                   .
                   .
                   .

最后在你的 .ts 代码中,你的 drop 函数:

import {CdkDragDrop, moveItemInArray, transferArrayItem} from '@angular/cdk/drag-drop';
  .
  .
  .
  .
 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);
    }
  }
}

如果你有很多扩展面板,勾选CdkDropListGroup