【问题标题】:Save order on page refresh of cdkDrag, cdkDropList Angular MaterialcdkDrag,cdkDropList Angular Material的页面刷新保存顺序
【发布时间】:2020-06-17 19:49:07
【问题描述】:

简介

我有一个待办事项列表,它在 cdkDropList 内的元素上利用 Angular Material 的 cdkDrag 指令。将项目标记为“待办事项”或“已完成”,反之亦然。

问题

用户交互中存在一定程度的细节,即页面刷新,这会导致项目不一定按照它们被拖动的顺序。

以这个例子为例,其中一个用户被分配了 3 个任务:吃早餐吃午餐吃晚餐

用户不喜欢该优先级,并决定改为按此顺序处理他/她的饮食任务。拖放交互发生,待办事项列表最终确定为:

在页面刷新时,这就是问题所在。它会回到原来的状态:

吃早餐吃午餐吃晚餐

什么时候应该是:

吃晚餐吃早餐吃午餐

这个观察结果也适用于标记为完成的项目。

我需要确认此交互的当前状态缺少什么。请注意,此实现基于How To Build an App With Drag and Drop With Angular

感谢您的宝贵时间。

【问题讨论】:

  • 您是否将订单保存在某处,因为刷新页面会重置状态,一切都会丢失。
  • 不,只是对假后端的 CRUD 操作以更新项目。如果我要“保存订单”,您有什么想法来启动保存?
  • 要么有一个保存按钮,要么有一个由 drop 事件触发的保存,如果你想确保用户即使刷新也能保持他所做的事情,而不是我建议在每次 drop 时保存。使用更新的列表发送保存操作(应该保持订单),并将订单属性添加到您的后端。然后在启动时(组件的 OnInit)调度一个初始化数据的操作(获取待办事项列表和您需要的所有其他内容)

标签: javascript angular angular-material angular-cdk angular-cdk-drag-drop


【解决方案1】:

您需要将“字符串”数组转换为“对象”数组

想象一下你有一个数组,比如

[{task:"eat breakfast",order:0},
 {task:"eat lunch",order:1},
 {task:"eat dinner",order:2}
]

在您的放置函数中,您需要重新计算属性顺序。使用典型的 drop 函数

drop(event: CdkDragDrop<any[]>) {
    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);
      //if transfer, recalculate the order of previous (the list from drag)
      event.previousContainer.data.forEach((x,index)=>{
          x.order=index
      })
    }
    //always, recalculate the order of the container (the list to drag)
      event.container.data.forEach((x,index)=>{
          x.order=index
      })
  }

那么你无论如何都需要保存数据(我认为你可以使用 ngOnDestroy),当你收到数据时不要忘记按顺序排序

注意:在this SO 中有一个使用 formArray 的 cdkDragList(仅用于排序)如果你想使用 FormArray 但它不是必需的,只有两个数组必须足够

【讨论】:

  • ERROR TypeError: Cannot assign to read only property 'order' of object '[object Object]' - 看起来事件容器内的数据是只读的。
  • 问题是参数事件中的类型,必须是“任何”drop(event: CdkDragDrop&lt;any[]&gt;){..},请参阅工作演示:stackblitz.com/edit/angular-vy2xfm?file=src/app/…(刚刚在答案中更正)。我无法回复您的问题
  • 您之前的示例按预期工作。但是原始文章中的工作示例利用 NGRX 进行状态管理。我认为这比我试图在重新计算时更改不可变对象时看起来更复杂。
  • 仅按照建议,尝试使用“map”创建一个新的对象数组,添加属性“order”并使用最后一个对象数组,或者,如果您有接口添加属性 order 可选跨度>
  • 谢谢,Eliseo。最后一轮的建议有所帮助。我已经有了一个接口,所以添加了 order 属性的可选选项。我在一个新变量中引用了只读对象,然后对我的 drop() 函数内部的一个本地可变对象执行了映射操作。请注意,我正在通过 NgRx 进行状态管理,因此没有后端关系到保存订单的状态。谢谢,这是最终结果:stackblitz.com/edit/angular-tasklist-ng9
猜你喜欢
  • 2014-12-29
  • 2020-11-08
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 2019-03-08
相关资源
最近更新 更多