javascript - Jquery-UI 可排序列表不能很好地处理 Meteor 模板中的响应式(Reactive)更新

标签 javascript jquery-ui meteor meteor-blaze

我正在尝试以 http://differential.com/blog/sortable-lists-in-meteor-using-jquery-ui 中描述的方式使用 JQuery-UI 实现可排序的对象列表.

但是,我不是对单独的文档列表进行排序,而是对嵌入在单个文档中的对象列表进行排序。也就是说,我有这样一个文档:

{  name: "Name of this Rolodex",
   cards: [{name: "...", rank: 0, id: "some-unique-id"},
           {name: "...", rank: 1, id: "some-other-unique-id"}, ... ]
}

我只是想让卡片可以排序。我的模板如下——它传递了一个 Rolodex 作为上下文:

<template name="rolodex">
  Rolodex Name: {{name}}
  <div class="cards-list">
    {{#each sortedCards}}
      {{> cardTemplate}}
    {{/each}}
  </div>
</template>

和辅助 JS 文件:

Template.rolodex.helpers({
  sortedCards: function() {
    return this.cards.sort(function(cardA, cardB) {
      return cardA.rank - cardB.rank;
    });
  }
});

Template.rolodex.rendered = function() {
  this.$(".cards-list").sortable({
    stop: function(e, ui) {
      // Get dragged HTML element and one immediately before / after
      var el = ui.item.get(0)
      var before = ui.item.prev().get(0)
      var after = ui.item.next().get(0)

      // Calculate new rank based on ranks of items before / after
      var newRank;
      if(!before) {
        // First position => set rank to be less than card immediately after
        newRank = Blaze.getData(after).rank - 1;
      } else if(!after) {
        // Last position => set rank to be more than card immediately after
        newRank = Blaze.getData(before).rank + 1;
      } else {
        // Average before and after
        newRank = (Blaze.getData(after).rank + 
                   Blaze.getData(before).rank) / 2;
      }

      // Meteor method that updates an attribute for a single card in a
      // Rolodex based on IDs for the Rolodex and Card
      Meteor.call('cards/update',
                  Blaze.getData(ui.item.parent().get(0))._id, // Rolodex ID
                  Blaze.getData(el).id, // Card ID
                  {rank: newRank});
    }
  });
};

我遇到的问题是,在将卡片分类到其预期位置后,DOM 随卡片更新到一个新的错误位置。尽管服务器存储了正确的排名,刷新页面会使卡片列在正确的位置(至少在尝试另一种排序之前)。

我对正在发生的事情的最佳猜测是 Meteor 的模板系统似乎不理解 JQuery-UI 已经移动了 DOM 元素并且正在以错误的顺序 react 性地更新我的模板。

例如,假设我的卡片是:A、B、C。我移动 C,这样我们现在有 C、A、B。JQuery-UI 相应地更新 DOM 并触发一个事件,导致 C 的排名更改为低于 A。

但是,Meteor 并不知道 DOM 已经被 JQuery-UI 改变了。但是,它确实看到了 C 等级的变化,并根据先前关于列表顺序的假设 react 性地更新了列表的顺序。在这种情况下,我们最终得到 B、C、A。

关于我在这里做错了什么有什么建议吗?

最佳答案

Meteor/Blaze 使用 _id 属性来识别数据对象并将它们链接到 DOM 元素。这不仅适用于 Collection 游标返回的文档数组,也适用于任何对象数组。所以在上面的问题中,问题是我使用了 id 值来标识每张卡,而不是 _id。将 id 切换为 _id 可解决问题并允许 Blaze 正确更新 DOM,即使 DOM 之前已被 JQuery-UI 的可排序插件修改。

关于javascript - Jquery-UI 可排序列表不能很好地处理 Meteor 模板中的响应式(Reactive)更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26944421/

相关文章:

javascript - jQuery off() 不删除点击处理程序

javascript - 在利用子元素的属性时将事件监听器添加到多个元素

javascript - 无法变换旋转地球仪上的标签

email - 如何为 Meteor 电子邮件 sendMail 配置 SSL?

javascript - 从没有弹出窗口拦截器的预签名 URL 下载 S3 文件

javascript - 鼠标悬停时关闭下拉菜单的 jQuery 插件

IE 中的 JQuery 选项卡不显示图片

javascript - 在动态列表源的 jQuery 自动完成中突出显示查询

javascript - 使用 Javascript 或 css 从 div [方形] 的中心到 Angular 落设置背景颜色动画

javascript - 获取与父字段一起分配的所有文档