【问题标题】:ember-drag-sort: how to determine the new parent in the dragged list?ember-drag-sort:如何确定拖动列表中的新父级?
【发布时间】:2017-11-13 14:13:27
【问题描述】:

最初是由@andrewsydGitHub 上提出的。

对于嵌套列表,有没有办法在 dragEnd 操作中确定该项目已放入哪个“子列表”? (例如类名、id 等)

在我的场景中,我正在对可以属于彼此的 ember 数据记录进行排序(即嵌套的“树”结构)。当我将一个嵌套记录“拖入”另一个(使拖动的记录成为第二个记录的子记录)时,我需要更新 ember-data.xml 中的父属性。我的问题是,如何将第二条记录(新父项)的一些 id 传递给 dragEnd 操作?

这可能吗?

【问题讨论】:

    标签: javascript ember.js ember-data ember-drag-sort


    【解决方案1】:

    解决方案 0:调整您的数据模型以将 isParent 属性转换为派生值而不是事实来源

    拥有必须手动更新的isParent 属性首先是一种有缺陷的方法。

    如果您将isParent 状态作为属性并要求前端对其进行更新,那么您有两个可能(并且最终会)不同步的事实来源。尤其是考虑到用户可以篡改对您的 API 后端的网络请求这一事实。

    isParent 应该是从孩子的数量中推断出来的。它可以是一个简单的计算属性:

    {
      isParent: computed('children.[]', function () {
        return this.get('children.length') > 0
      }
    }
    

    可以在后端使用类似的方法。

    如果您不控制后端并且仍需要从前端更新 isParent 属性,我建议您破解您的序列化程序以在序列化期间将 isParent 计算属性值包含到有效负载中。

    虽然我坚信您应该采用此解决方案,但我在下面研究了几个替代解决方案。

    方案一:使用观察者自动更新父状态

    在您的模型中:

    {
      updateParentState: Ember.observer('children.[]', function () {
       const isParent = this.get('children.length') > 0
        this.setProperties({isParent})
      })
    }
    

    这将使isParent 属性与其children 关系在更新时保持同步。

    这是一个演示:https://ember-twiddle.com/f1c737d3bc106cb9cca071fd01fe334f?openFiles=models.item.js%2C

    请注意,如果您在拖动结束时自动保存记录,则应将保存包装到Ember.run.next,以便在观察者触发后进行保存。

    解决方案2:访问被拖动项的新旧父项

    鉴于您已经建立了这样的关系:

    export default Model.extend({
      isParent: attr('boolean'),  
      parent: belongsTo('item', {inverse: 'children'}),
      children: hasMany('item', {inverse: 'parent'}),
    })
    

    ...您可以在拖动结束动作中访问被拖动项目的新旧父项!

    {
      actions : {
        dragEnd ({sourceList, sourceIndex, targetList, targetIndex}) {
          if (sourceList === targetList && sourceIndex === targetIndex) return
    
          const draggedItem = sourceList.objectAt(sourceIndex)
          const oldParent = draggedItem.get('parent')                     // <--
    
          sourceList.removeAt(sourceIndex)
          targetList.insertAt(targetIndex, draggedItem)
    
          const newParent = draggedItem.get('parent')                     // <--
    
          newParent.set('isParent', newParent.get('children.length') > 0) // <--
          oldParent.set('isParent', oldParent.get('children.length') > 0) // <--
        },
      }
    }
    

    我已经用箭头 cmets 标记了相关行。

    看,您在移动之前从拖动的项目中读取了旧的父项。移动项目后,您将读取新的父项。这是可能的,因为 Ember Data 会自动执行关系簿记。

    最后,您更新父母双方的isParent 状态。

    演示:https://ember-twiddle.com/ab0bfdce6a1f5ad4bd0d1c9c45f642fe?openFiles=controllers.application.js%2Ctemplates.components.the-item.hbs

    【讨论】:

      猜你喜欢
      • 2019-01-30
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 2016-03-10
      • 1970-01-01
      相关资源
      最近更新 更多