[英]Meteor AutoForm: How to update schema values with array of sub-documents?
[英]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.