简体   繁体   English

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

[英]How to transfer an array item to another array and update it using Angular Material Drag n Drop CDK without both items binding to the same paramter

I'm using Angular Material Drag N Drop CDK to move a set of default items (List 1) to a list of dynamic items (List 2).我正在使用 Angular Material Drag N Drop CDK 将一组默认项目(列表 1)移动到动态项目列表(列表 2)。 When I drag a default item (L1) into the dynamic items (L2) and then update the now dynamic item(New L2 Items), it also updates the default item (Old L1 Item) as well.当我将默认项目 (L1) 拖到动态项目 (L2) 中,然后更新现在的动态项目(新 L2 项目)时,它也会更新默认项目(旧 L1 项目)。

When you drag a default item (L1) to the dynamic item (L2), the default list (L1) resets back to its original array with a resetList method.当您将默认项 (L1) 拖动到动态项 (L2) 时,默认列表 (L1) 将使用 resetList 方法重置回其原始数组。 My goal is to update the now dynamic item (New L2 Item) and to potentially drag the same default item (Old L1 Item that was reset) into the dynamic list (L2) creating another new dynamic item (Another New L2 Item).我的目标是更新现在的动态项目(新 L2 项目)并可能将相同的默认项目(重置的旧 L1 项目)拖到动态列表(L2)中,以创建另一个新的动态项目(另一个新的 L2 项目)。 The problem Im running into is, when I drag a default item (L1) into the dynamic list (L2), then update the new dynamic item (New L2 Item using ngModel) the default item (Old L1 Item) that was dragged and reset also updates.我遇到的问题是,当我将默认项 (L1) 拖动到动态列表 (L2) 中时,然后更新新的动态项(使用 ngModel 的新 L2 项)被拖动并重置的默认项(旧 L1 项)还更新。

Here is my html in form.component.html这是我在 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>

Here is my form.component.ts file这是我的 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);    
      }

Im expecting to be able to drag an item from L1 to L2 and update it successfully using ngModel.我希望能够将一个项目从 L1 拖到 L2 并使用 ngModel 成功更新它。 In this specific use-case, I want to change the placeholder which is a parameter in the Answer class.在这个特定用例中,我想更改占位符,它是 Answer 类中的一个参数。

Whats actually happening is, Item from L1 and New Item from L2 both update as if they're binding to the same parameter.实际发生的是,来自 L1 的 Item 和来自 L2 的 New Item 都更新,就好像它们绑定到相同的参数一样。 Therefor I can't update item from L2 without changing L1.因此,我无法在不更改 L1 的情况下从 L2 更新项目。 If I also add the same item from L1 into L2 again (which I can do because the list is reset), all three items (L1, L2 New and 2nd L2 New) will update using ngModel.如果我还将 L1 中的相同项目再次添加到 L2(我可以这样做,因为列表已重置),所有三个项目(L1、L2 新建和第二个 L2 新建)都将使用 ngModel 进行更新。

*******UPDATE - REPRODUCED STACKBLITZ I was able to reproduce the error in stackblitz. ******* 更新 - 重现的 STACKBLITZ 我能够在 stackblitz 中重现错误。 You may have to refresh the page to get the drag n drop to work.您可能需要刷新页面才能让拖放操作生效。

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

You'll need to create a copy of the original item, then add the copy to the 2nd list.您需要创建原始项目的副本,然后将副本添加到第二个列表中。 There are a lot of ways to copy an object but basically something like this:有很多方法可以复制对象,但基本上是这样的:

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

replace代替

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);
    }
}

请确认在哪里调用这个复制数组的函数>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM