Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/435.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Meteor Blaze按子文档属性排序子文档_Javascript_Arrays_Sorting_Meteor_Reactive Programming - Fatal编程技术网

Javascript Meteor Blaze按子文档属性排序子文档

Javascript Meteor Blaze按子文档属性排序子文档,javascript,arrays,sorting,meteor,reactive-programming,Javascript,Arrays,Sorting,Meteor,Reactive Programming,简介: _id: Pe0t3K8GG8, videos: [ {id:'HdaZ8rDAmy', url:'VIDURL', rank: 2}, {id:'22vZ8mj9my', url:'VIDURL2', rank: 0}, {id:'8hyTlk8H^6', url:'VIDURL3', rank: 1}, ] 配置文件将与视频列表一起显示。我有一个使用服务器方法更新视频排名的拖放 1) 数据库在拖放时正确更新 2) 要对视频数组进行排序-我在配置文件模板上声明了一个

简介:

_id: Pe0t3K8GG8,
videos: [
   {id:'HdaZ8rDAmy', url:'VIDURL', rank: 2},
   {id:'22vZ8mj9my', url:'VIDURL2', rank: 0},
   {id:'8hyTlk8H^6', url:'VIDURL3', rank: 1},
]
配置文件将与视频列表一起显示。我有一个使用服务器方法更新视频排名的拖放

1) 数据库在拖放时正确更新

2) 要对视频数组进行排序-我在配置文件模板上声明了一个助手,并基于自定义比较函数对视频数组进行排序

Template.Profile.helpers({
    'videosSorted': function(){
        let videos = (this.videos);
        let videosSorted = videos.sort(function(a, b) {
        return parseFloat(a.rank) - parseFloat(b.rank);
    });
    return videosSorted;
  }
});
问题: A) 在Blaze中,
{{#each videosSorted}}
不会进行反应性更新。 如果我刷新F5,那么我可以看到新订单

我认为这个问题是因为我提供了VideosOrted,它不会随着数据库中文档的更改而更新

我怎样才能使录像带反应性强

更新: 所有相关代码: Iron Router Controller-我订阅并设置布局的数据上下文

ProfileController = RouteController.extend({
 subscriptions: function() {
    this.subscribe('profile',this.params.slug).wait();
  },
  data: function () {
     //getting the data from the subscribed collection
     return Profiles.findOne({'slug':this.params.slug});
  },
})
出版物:

Meteor.publish('profile', function (slug) {
  const profile = Profiles.find({"slug":slug});
  if(profile){
    return profile;
  }
  this.ready();
});
配置文件HTML模板:

<template name="Profile">
     <ul  class="sortlist">
        {{#each videosSorted}}
            {{> Video}}
        {{/each}}
     </ul>
</template>
最后是进行更新的Meteor方法

'updateVideoPosition': function (queryData){
    let result = Individuals.update(
      {_id: queryData._id, 'videos.objId': queryData.videos_objId },
      { $set:{ 'videos.$.rank' : queryData.new_rank } }
    )
    return result;
  }
注意: 正如我所提到的——数据库更新正确——如果我有一个匿名窗口打开到同一个页面——我会看到视频反应(神奇地!)切换到新的顺序

模式
我提出了一个非常粗糙的解决方案,但我现在看不到其他选择。我能想到的最简单的解决方案是手动重新提交模板:

Template.Profile.onRendered(function () {
  var self = this;
  var renderedListView;
  this.autorun(function () {
    var data = Template.currentData(); // depend on tmeplate data
    //rerender video list manually
    if (renderedListView) {
      Blaze.remove(renderedListView);
    }
    if (data) {
      renderedListView = Blaze.renderWithData(Template.VideoList, data, self.$('.videos-container')[0]);
    }
  });
});
Template.VideoList.onRendered(function () {
  var tmpl = this;
  tmpl.$('.sortlist').sortable({
    stop: function (e, ui) {
      var el = ui.item.get(0);
      var before = ui.item.prev().get(0);
      var after = ui.item.next().get(0);
      var newRank;
      if (!before) {
        newRank = Blaze.getData(after).rank - 1
      } else if (!after) {
        newRank = Blaze.getData(before).rank + 1
      }
      else {
        newRank = (Blaze.getData(after).rank +
          Blaze.getData(before).rank) / 2
      }
      let queryData = {
        _id: tmpl.data._id,    //the id of the profile record
        videos_objId: Blaze.getData(el).objId,    //the id of the sub document to update
        new_rank: newRank  //the new rank to give it
      };
      //Update the sub document using a server side call for validation + security
      Meteor.call("updateVideoPosition", queryData, function (error, result) {
        if (!result) {
          console.log("Not updated");
        }
        else {
          console.log("successfully updated Individual's Video Position")
        }
      });
    }
  });
});
Template.VideoList.helpers({
  videosSorted: function () {
    return this.videos.sort(function (a, b) {
      return a.rank - b.rank;
    });
  }
});
和HTML:

<template name="Profile">
  <div class="videos-container"></div>
</template>

<template name="VideoList">
  <ul class="sortlist">
    {{#each videosSorted}}
      <li>{{url}}</li>
    {{/each}}
  </ul>
</template>

    {{{#每个视频剪辑}
  • {{url}}
  • {{/每个}}
在您的案例中,由于JQuery UI Sortable,创造性丧失了。它对Meteor的反应性一无所知,只是简单地阻止了模板的重新提交


也许你应该考虑使用更多的用于流星的东西(我不确定它是否适合你的需要)。

如果你做了代码>让视频=这个视频,SLICE()/代码>你的集合是如何定义的?所有的助手都是反应性的,并且依赖于<代码> CurrutDATA()/<代码>。因此,您的助手应该反应性地工作。可能您在以前的模板级别上失去了反应性。你能发布与视频文档相关的所有js/html代码吗?@Tdm I已经更新了更新标题下方的问题。诊断。在对mongo进行异步更新之前,正在调用VideosOrted帮助程序。在方法返回后,如何调用该助手手动运行。
Template.Profile.onRendered(function () {
  var self = this;
  var renderedListView;
  this.autorun(function () {
    var data = Template.currentData(); // depend on tmeplate data
    //rerender video list manually
    if (renderedListView) {
      Blaze.remove(renderedListView);
    }
    if (data) {
      renderedListView = Blaze.renderWithData(Template.VideoList, data, self.$('.videos-container')[0]);
    }
  });
});
Template.VideoList.onRendered(function () {
  var tmpl = this;
  tmpl.$('.sortlist').sortable({
    stop: function (e, ui) {
      var el = ui.item.get(0);
      var before = ui.item.prev().get(0);
      var after = ui.item.next().get(0);
      var newRank;
      if (!before) {
        newRank = Blaze.getData(after).rank - 1
      } else if (!after) {
        newRank = Blaze.getData(before).rank + 1
      }
      else {
        newRank = (Blaze.getData(after).rank +
          Blaze.getData(before).rank) / 2
      }
      let queryData = {
        _id: tmpl.data._id,    //the id of the profile record
        videos_objId: Blaze.getData(el).objId,    //the id of the sub document to update
        new_rank: newRank  //the new rank to give it
      };
      //Update the sub document using a server side call for validation + security
      Meteor.call("updateVideoPosition", queryData, function (error, result) {
        if (!result) {
          console.log("Not updated");
        }
        else {
          console.log("successfully updated Individual's Video Position")
        }
      });
    }
  });
});
Template.VideoList.helpers({
  videosSorted: function () {
    return this.videos.sort(function (a, b) {
      return a.rank - b.rank;
    });
  }
});
<template name="Profile">
  <div class="videos-container"></div>
</template>

<template name="VideoList">
  <ul class="sortlist">
    {{#each videosSorted}}
      <li>{{url}}</li>
    {{/each}}
  </ul>
</template>