繁体   English   中英

Meteor Blaze按子文档属性订购子文档

[英]Meteor Blaze order sub-documents by sub-document property

轮廓:

_id: Pe0t3K8GG8,
videos: [
   {id:'HdaZ8rDAmy', url:'VIDURL', rank: 2},
   {id:'22vZ8mj9my', url:'VIDURL2', rank: 0},
   {id:'8hyTlk8H^6', url:'VIDURL3', rank: 1},
]

配置文件与视频列表一起显示。 我有一个拖放功能,可使用服务器方法更新视频排名。

1)数据库在Drop上正确更新。

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不会更新数据库中文档的更改。

如何使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>

我正在使用mrt:jquery-ui-可排序函数

Template.Profile.onRendered(function () {
  thisTemplate = this;

  this.$('.sortlist').sortable({
    stop: function(e, ui) {

      el = ui.item.get(0);
      before = ui.item.prev().get(0);
      after = ui.item.next().get(0);

      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: thisTemplate.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")
          }
      });
   }
 })
});

最后是进行更新的Meteor方法

'updateVideoPosition': function (queryData){
    let result = Individuals.update(
      {_id: queryData._id, 'videos.objId': queryData.videos_objId },
      { $set:{ 'videos.$.rank' : queryData.new_rank } }
    )
    return result;
  }

注意 :

正如我提到的那样-数据库正确更新-并且如果我在同一页面打开了“隐身”窗口-我会看到视频重新激活(神奇地是!)切换到新顺序。

模式

const ProfileSchema = new SimpleSchema({
  name:{
    type: String,
  }
  videos: {
    type: [Object],
    optional:true,
  },
  'videos.$.url':{
    type:String,
  },
  'videos.$.rank':{
    type:Number,
    decimal:true,
    optional:true,
    autoform: {
      type: "hidden",
    }
  },
  'videos.$.subCollectionName':{
    type:String,
    optional:true,
    autoform: {
      type: "hidden",
    }
  },
  'videos.$.objId':{
    type:String,
    optional:true,
    autoform: {
      type: "hidden",
    }
  } 
});

我想出了真正的粗略解决方案,但现在没有其他选择。 我能想到的最简单的解决方案是手动重新呈现模板:

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>

由于JQuery UI Sortable,您的情况失去了可靠性。 它对Meteor的反应性一无所知,只是阻止了模板的重新渲染。

也许你应该考虑使用更采用了流星喜欢的事, (我不知道它适合你的需求)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM