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

Jon*_*rin 9 javascript angular-material angular

我正在使用Angular Material Drag N Drop CDK将一组默认项目(List 1)移动到动态项目列表(List 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>
Run Code Online (Sandbox Code Playgroud)

这是我的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);    
      }
Run Code Online (Sandbox Code Playgroud)

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

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

*******UPDATE - REPRODUCED STACKBLITZ我能够重现stackblitz中的错误.您可能必须刷新页面才能使拖动工作正常.

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
Run Code Online (Sandbox Code Playgroud)

Mik*_*man 5

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

function createCopy(orig){
   return  JSON.parse(JSON.stringify(orig))
}
Run Code Online (Sandbox Code Playgroud)