【问题标题】:Push last object in array to the next array将数组中的最后一个对象推送到下一个数组
【发布时间】:2020-01-31 13:46:09
【问题描述】:

我有一个这样的对象:

container = {
    row1: [ '1', '2', '3', '4' ],
    row2: [ '5', '6', '7', '8' ],
    row3: [ '9', '10', '11', '12' ]
  }

此数据填充我的 Angular 项目中的网格拖放组件。

当一个“项目”从一个数组移动到另一个数组时,我希望该数组中的最后一项移动到下一个数组并将所有对象向前推 1,这样我就可以确保其中只有 4 个对象每个数组。

我怎样才能做到这一点?我已经玩了太多小时了!

我有这个 '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);
    }
  }

所以我现在需要的是:

this.container.data.unshift() //to the next array within the container array.

我也可以在我的组件中访问这个数组,所以甚至可以传入行名:

drop(event: CdkDragDrop<string[]>, rowName: 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);
    }
  }

我该如何做到这一点,如果需要的话,能够扭转它也很好。

这里是 StackBlitz:https://stackblitz.com/edit/angular-cdk-drag-drop-cmyh7k?file=app%2Fcdk-drag-drop-connected-sorting-example.html

【问题讨论】:

  • 你的内部数组总是 4 个元素大吗?如果你从第一个数组中取出一个元素并把它扔到第二个数组中会发生什么?第一个数组是否被 3 个元素卡住了?有空吗?将一个元素扔到最后一个数组中怎么样?我们最后会得到一个新的 1 元素数组吗?
  • 最初是的,但我打算尝试使其动态化,因此您可以使用变量来设置它,它可以是 2、4 或 6,并且可以设置每行上的对象数跨度>
  • 我建议你只有一个数组,而不是对象数组,你将计数器设置为 0,循环遍历这个数组,然后每次计数器为 4 时创建一个新行然后将计数器重置为 0。这样你就不需要过滤,你可以在任何地方注入新项目。
  • 为了清晰起见,我将创建一个堆栈闪电战

标签: javascript arrays angular typescript


【解决方案1】:

首先,您需要更新 stackblitz 的引用以获取新版本的 Angular 8 和 cdk。也删除 pollyfill.ts 中对 core.js 的引用。

这使得你可以在行之间拖动

将“drop function”改成如,例如

drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      const dataFrom=event.previousContainer.data[event.previousIndex]
      const dataTo=event.container.data[event.currentIndex]
      event.previousContainer.data.splice(event.previousIndex,1,dataTo)
      event.container.data.splice(event.currentIndex,1,dataFrom)

    }
  }

您不必强制使用“transferArrayItem”函数。你在 event.previousContainer.data 中有数据,在 event.container.Data 中有数据,所以你可以“播放”使用 splice 从另一个元素中删除一个元素。

在我的例子中,我使用 indexex 来交换位置,但你可以按照你想要的方式进行

提示:创建 event.previousContainer.data、event.container.data、event.previousIndex 和 event.currentIndex 的 console.log() 来查看值很有趣

这里是your forked stackbliz

更新另一个功能

drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      //get the data we are dragging
      const dataFrom=event.previousContainer.data[event.previousIndex]
      //get the last element of the row where dropped
      const dataTo=event.container.data[event.container.data.length-1]

      //remove the element dragged
      event.previousContainer.data.splice(event.previousIndex,1)
      //Add at last the dataTo
      event.previousContainer.data.push(dataTo)

      //Add the data dragged
      event.container.data.splice(event.currentIndex,0,dataFrom)
      //remove the last element
      event.container.data.pop()

    }
  }

Update2 看起来有些“奇怪”,所以我们可以考虑如果使用 (cdkDropListEntered) (cdkDropListExited) 和 (cdkDragStarted) 可以改善更好的效果。

这个想法是为每一行添加一个元素,如果我们重新排列该行或者我们没有拖动任何东西,则该元素将不可见(显示:无)。如果我们在行之间拖动,该元素将获取我们被拖放的行的最后一个元素的值。

噗,先声明三个变量

  fade=[" "," "," "]   //to show the elements
  indexDrag:number=-1  //the row from we picked the element
  indexEnter:number=-1  //the row where we want dropped the element

我们要在拖拽项前添加一个div

<div cdkDropList cdkDropListOrientation="horizontal" 
  [cdkDropListData]="container.row1" class="example-list"
  (cdkDropListDropped)="drop($event)" 
  (cdkDropListEntered)="enter($event,0)" > //<--for the second row will be enter($event,1)
                                           // and for the third row enter($event,2)
  <!-- our element before the drags elements -->
  <div class="example-box" 
        [style.display]="(indexDrag!=0 ||
                          indexEnter==indexDrag || 
                          indexEnter<0)?'none':null">
    <div class="tile">
      <div class="tile-container">{{fade[0]}}</div>
    </div>
  </div>
  <!--our dragabbles elements -->
  <div class="example-box" *ngFor="let item of container.row1" cdkDrag 
     (cdkDragStarted)="startDrag(0)"> //<--for the second row will be startDrag(1)
                                      //  and startDrag(2) for the third row
    <div class="tile">
      <div class="tile-container">{{item}}</div>
    </div>
  </div>

然后,只需添加两个函数

  startDrag(index) {
    this.indexDrag=index;
  }
  enter(event: CdkDragEnter<any>,index) {
    this.indexEnter=index;
    const data=event.container.data
    this.fade[this.indexDrag]=data[data.length-1]
  }

并且,在 drop 函数中,我们“重新启动”变量 indexDrag、indexEnter 和 fade

  drop(event: CdkDragDrop<string[]>) {

    this.indexDrag = -1;
    this.indexEnter = -1;
    this.fade=[" "," "," "]
     ...rest of the code..
  }

new stackblitz中的结果

嗯,有一个问题,因为我们可以拖过一行的 las 元素并且应用程序失败了,抱歉。所以我们需要做出另一个改变

在 drop 函数中检查 currentIndex 是否等于 data.length

    const currentIndex=(event.currentIndex==event.container.data.length)?
              event.container.data.length-1:event.currentIndex

在 div 中创建另一个 *ngIf 是最后一个

    <div class="tile" *ngIf="!last || indexEnter!=1 || indexEnter==indexDrag">
      <div class="tile-container">{{item}}</div>
    </div>

【讨论】:

  • 感谢 Eliseo,这已经差不多了。我也想过切换位置而不是向前推动所有对象,但不幸的是,当您将鼠标悬停在容器上以放下一个项目时,它会向上移动下一个项目,然后当您放下它时,它会切换。我怎样才能避免这种情况?
  • 我更新了答案,我认为它更接近您的要求
  • 非常接近。我使用了“unshift()”而不是“push()”,并且成功了!非常感谢这个
  • 我已将此标记为正确,因为它与我想要实现的目标足够接近,但如果您有足够的时间,我真的很想利用 enter() 和 exited() 方法,以便'项目'在进入时推动并在退出时移除以产生更好的效果 - 感谢您的帮助,非常感谢
  • @DBoi,考虑更好的效果,我更新了答案。简单的想法是在每一行之前添加一个固定元素,并在我们在行之间放置时使其可见。真的我在相反的情况下做到了(显示:无)
猜你喜欢
  • 2020-08-23
  • 2021-11-12
  • 2017-03-02
  • 1970-01-01
  • 2017-10-10
  • 2017-07-01
  • 2021-09-21
  • 1970-01-01
  • 2019-12-22
相关资源
最近更新 更多