如何将一个数组项目转移到另一个数组,并使用Angular Material Drag n Drop CDK更新它,而两个项目都不绑定到同一参数上

问题描述 投票:9回答:2

我正在使用Angular Material拖动N Drop CDK将一组默认项目(列表1)移动到动态项目列表(列表2)。当我将默认项目(L1)拖到动态项目(L2)中,然后更新现在的动态项目(新L2项目)时,它也会同时更新默认项目(旧L1项目)。

当将默认项(L1)拖动到动态项(L2)时,默认列表(L1)使用resetList方法重置回其原始数组。我的目标是更新现在的动态项目(新的L2项目),并可能将同一默认项目(已重置的旧L1项目)拖到动态列表(L2)中,从而创建另一个新的动态项目(另一个新的L2项目)。我遇到的问题是,当我将默认项(L1)拖动到动态列表(L2)中,然后更新新的动态项(使用ngModel的新L2项)时,将默认项(旧L1项)拖动并重置也更新。

这是我在form.component.html中的html

<!-- Default Answer List - List 1 -->
 <aside cdkDropList id="defaultAnswerList"
            [cdkDropListConnectedTo]="['dynamicAnswerList']" [cdkDropListData]="defaultAnswers">
            <div class="aside-container">
                <div class="auto-complete-content-area p-10">
                    <div *ngFor="let answer of defaultAnswers">
                        <!-- answer.isInput - Text Input -->
                        <div class="element-wrapper addon-group" *ngIf="answer.isInput" cdkDrag>
                            <div class="label-side">
                                Short Text
                            </div>
                            <div class="element-side">
                                <input type="text" [(ngModel)]="answer.placeholderText" class="input-element"
                                    placeholder="Placeholder" />
                                <label>Drag to add a short text answer</label>
                            </div>
                        </div>
          </div>
       </div>
    </aside>

<!-- Dynamic Answer List - List 2-->
<div class="input-answers" cdkDropList id="dynamicAnswerList"
                    (cdkDropListDropped)="dropIt($event)" [cdkDropListData]="dynamicAnswers">
                        <div class="input-section" cdkDragLockAxis="y" style="cursor: all-scroll" *ngFor="let answer of dynamicAnswers; index as i"
                            cdkDrag>
                            <div class="input-wrapper" *ngIf="answer.isInput || answer.isAddressSearch || answer.isAgeInput || answer.isVehicleVIN">
                                <input type="text" class="input-box normal-input-box" [(ngModel)]="answer.placeholderText"
                                    placeholder="Add Text Placeholder" />
                            </div>
                        </div>
                    </div>

这是我的form.component.ts文件

// Here is the original array which is then set to defaultAnswers
defaultAnswersOrigin: Answer[] = [
        {isInput: true, placeholderText: "Enter Placeholder", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", width: "45", position: 0},
        {isDatePicker: true, placeholderText: "Enter Date Placeholder", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", width: "45", position: 1},
        {isSelect: true, placeholderText: "Enter Menu Placeholder", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", width: "45", position: 2},
        {isTextarea: true, secondaryPlaceholderText: "Enter Text Placeholder", hasSecondaryPlaceholder: true, hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", width: "45", position: 3},
        {isCheckbox: true, displayValue: "", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", width: "45", position: 4},
        {isButton: true, placeholderText: "", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", displayValue: "Enter Button Text", width: "45", position: 5},
        {isPrevNextButtons: true, placeholderText: "", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", displayValue: "", width: "90", position: 6},
        {isProgressButton: true, placeholderText: "", hasPrefix: false, hasSuffix: false, prefixText: "", suffixText: "", displayValue: "", width: "90", position: 7}
    ];

 defaultAnswers = this.defaultAnswersOrigin;
 answers: Answers = [];

   // Drop it method used in html
    dropIt(event: CdkDragDrop<string[]>) {
        if (event.previousContainer !== event.container) {
            transferArrayItem(this.defaultAnswers,
                                 this.answers,
                                 event.previousIndex,
                                 event.currentIndex);
                this.answers.forEach((answer, i) => {
                    answer.position = i;
                });
            this.resetList();
        } else if (event.previousIndex !== event.currentIndex) {
            if (event.previousContainer === event.container) {
                moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
            }
        }
      }

// Reset list method used
     resetList() {
        this.defaultAnswers = [];
        setTimeout(() => {
          this.defaultAnswers = this.defaultAnswersOrigin.slice();
        }, 0);    
      }

我期望能够将项目从L1拖到L2并使用ngModel成功更新。在这个特定的用例中,我想更改占位符,它是Answer类中的一个参数。

实际发生的是,L1中的项目和L2中的新项目都更新,就好像它们绑定到同一个参数一样。因此,如果不更改L1,就无法从L2更新项目。如果我还将L1中的同一项目再次添加到L2中(由于列表已重置,所以可以这样做),所有三个项目(L1,L2 New和2nd L2 New)都将使用ngModel更新。

*******更新-复制的堆栈BLITZ我能够在stackblitz中重现该错误。您可能必须刷新页面才能使拖动n起作用。

Steps to reproduce: 
1. go to url below
2. Drag a Short Text item from Default List into Dynamic List
3. Start changing the new items placeholder in Dynamic List
4. Notice how placeholder in reset Default list is changing as well
5. Add same item from Default list to Dynamic list again
6. Change placeholder of new item
7. Notice how all three placeholders change now
https://stackblitz.com/edit/cdk-drag-and-drop-q7qqvo
javascript angular angular-material
2个回答
4
投票

您需要创建原始项目的副本,然后将该副本添加到第二个列表中。复制对象有很多方法,但是基本上是这样的:

function createCopy(orig){
   return  JSON.parse(JSON.stringify(orig))
}

1
投票

替换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); } } //with drop(event: any) { if (event.previousContainer === event.container) { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else { copyArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex); } }

© www.soinside.com 2019 - 2024. All rights reserved.