【问题标题】:Trouble with Angular Drag and Drop角度拖放问题
【发布时间】:2021-02-06 22:22:30
【问题描述】:

我正在努力让用户拥有一个可以查看公司卡的页面。我希望能够创建容器或只是一些他们可以用来组织它们的排序对象。 我创建了一个我希望它基于的 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, 显示整个卡片代码。

【问题讨论】:

    标签: html angular object drag-and-drop frontend


    【解决方案1】:

    Angular 材质 Drag&Drop 使用列表的概念。 您可以做的是连接列表(拖放,或在同一个列表中,或到另一个列表)。

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

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

    在您的扩展面板中:

    <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

    【讨论】:

    • 你的代码很好。尝试重新加载 vsCode,然后重新启动 Angular 服务器。你的 Angular 版本是什么?和角材料? ——
    • 我尝试关闭并重新启动服务器,它仍然无法正常工作并给我Property 'listOfAllCards' does not exist on type 'WatchlistComponent' 的错误,我的角度版本是 Angular CLI: 9.1.12,不,它只是单个扩展面板。不知道发生了什么。
    • 当我运行服务器时,拖动可以正常工作,看起来它会掉到扩展面板中,但是当我真正松开时,它就消失了。这可能是 listofAllcards 错误的一部分
    • 控制台说:未捕获的错误:cdkDrag 必须附加到元素节点。目前附加到“#comment”。在 CdkDrag._updateRootElement (drag-drop.js:4710) 在 SafeSubscriber._next (drag-drop.js:4615) 在 SafeSubscriber.__tryOrUnsub (Subscriber.js:183) 在 SafeSubscriber.next (Subscriber.js:122) 在 Subscriber ._next (Subscriber.js:72) 在 Subscriber.next (Subscriber.js:49) 在 TakeUntilSubscriber._next (Subscriber.js:72) 在 TakeUntilSubscriber.next (Subscriber.js:49) 在 TakeSubscriber._next (take.js :35) 在 TakeSubscriber.next (Subscriber.js:49)`
    • 非常感谢,它成功了。我希望你喜欢开心果冰淇淋!不过说真的,我很感激它,我肯定会尝试并将其放入自己的组件中以使其更小。我也一定会试试 stackblitz.com。也祝你晚安!
    猜你喜欢
    • 2019-03-23
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    相关资源
    最近更新 更多