我有一个模板chartEditPreview
,在渲染回调触发后运行D3.js图表绘制功能。它看起来像这样:
Template.chartEditPreview.rendered = function() {
drawChart(".chart-container", this.data);
}
其中.chart-container
是目标div,this.data
是当前正在访问的数据库中对象的数据。问题是,this.data
经常返回null
,似乎是随机的。看起来这与发布/订阅模式的工作方式有关 - Iron Router(我正在使用)让模板呈现,然后将数据热压到这些模板中。
我的问题(希望)非常简单:在运行this.data
之前,如何确保drawChart
实际上已经充满了数据库数据?我是否应该以其他方式执行此操作,而不是在呈现的回调上调用它?
我正在考虑在路由期间将DB数据存储在Session
变量中并从渲染中调用它,但这似乎是一个额外的步骤,我不确定它是否会解决这个问题。图表在页面上也只呈现一次 - 它是交互式的,因此每次通过屏幕上的一个输入更新数据库对象时,都需要重新绘制图表。
非常感谢任何帮助。谢谢!
供参考,这是我的routes.js的样子:
Router.route('/chart/edit/:_id', {
name: 'chart.edit',
layoutTemplate: 'applicationLayout',
yieldRegions: {
'chartEditType': { to: 'type' },
'chartEditPreview': { to: 'preview' },
'chartEditOutput': { to: 'output' },
'chartEditAside': { to: 'aside' },
'chartEditEmbed': { to: 'embed' }
},
data: function () {
return Charts.findOne({_id: this.params._id});
},
waitOn: function () {
return Meteor.subscribe('chart', this.params._id);
}
});
我的publications.js:
Meteor.publish("chart", function (id) {
return Charts.find({ _id: id });
});
答案 0 :(得分:1)
将this.ready()
添加到data:function
data: function () {
if(this.ready()){
return Charts.findOne({_id: this.params._id});
}else{
this.render('loading')
}
},
使用data
和waitOn
的东西可能有点棘手
Template.chartEditPreview.rendered = function() {
Meteor.setTimeout(function(){
drawChart(".chart-container", this.data);
},1000)
}
答案 1 :(得分:1)
这是Meteor的常见问题。虽然订阅可能已经准备就绪(您应该像Ethaan节目那样检查它),但这并不意味着find()函数实际上有时间返回一些内容。
通常我会用一些防御性代码解决它,即:
Template.chartEditPreview.rendered = function () {
if(this.data)
drawChart(".chart-container", this.data);
// else do nothing until the next deps change
}
当然这并不像应该的那样干净,但据我所知,这是解决这类问题的唯一方法。
更新回答 在这种情况下,我们需要一个依赖项来触发重新运行数据更改。 Iron路由器为我们解决了这个问题:
Template.chartEditPreview.rendered = function () {
var data = Router.current() && Router.current().data();
if(data)
drawChart(".chart-container", data);
// else do nothing until the next deps change
}