正确加载Template.templateName.rendered数据上下文 [英] Properly loading Template.templateName.rendered data context

查看:119
本文介绍了正确加载Template.templateName.rendered数据上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板, chartEditPreview ,运行一个D3.js图表​​绘制函数一旦渲染的回调触发。它看起来像这样:

I have a template, chartEditPreview, that runs a D3.js chart-drawing function once the rendered callback fires. It looks like this:

Template.chartEditPreview.rendered = function() {
  drawChart(".chart-container", this.data);    
}

其中 .chart-container 是目标div, this.data 是当前正在访问的DB中的对象的数据。问题是, this.data 经常返回 null ,看似随机。看起来这与发布/订阅模式的工作方式有关 - 铁路由器(我使用)让模板渲染,然后将数据热推送到这些模板。

Where .chart-container is the target div and this.data is the data for the object in the DB currently being accessed. Problem is, this.data often returns null, seemingly at random. It looks like this has something to do with how the publish/subscribe pattern works — Iron Router (which I'm using) lets the templates render and then hot-pushes the data into those templates.

我的问题是(希望)很简单:我如何确保 this.data 实际上在之前填充了DB数据drawChart 是否运行?我应该用其他方式做,而不是在渲染的回调函数调用它?

My question is (hopefully) pretty simple: how can I make sure this.data is actually full of DB data before drawChart is run? Should I be doing this in some other way, instead of calling it on the rendered callback?

我想把数据库数据存储在 Session 变量在路由和调用期间从呈现,但它似乎是一个额外的步骤,我不确定它会解决这个问题。图表也不会在页面上仅呈现一次 - 它是交互式的,因此每次通过屏幕上的输入更新数据库对象时,都需要重绘。

I'm thinking of storing the DB data in a Session variable during the routing and calling that from rendered, but it seems like an extra step, and I'm not certain it'll fix this problem. The chart's also not rendered only once on the page — it's interactive, so it needs to be redrawn every time the database object is updated via one of the inputs on screen.

任何帮助将不胜感激。谢谢!

Any help would be much appreciated. Thanks!

以下是我的routes.js的样子:

For reference, here's what my routes.js looks like:

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:

And my publications.js:

Meteor.publish("chart", function (id) {
  return Charts.find({ _id: id });
});


推荐答案

这是Meteor的常见问题。虽然订阅可能已经准备好了(你应该检查它像Ethaan显示的),这并不意味着find()函数实际上有时间返回一些东西。

This is a common problem with Meteor. While the subscription might be ready (you should check for it like Ethaan shows) , that does not mean the find() function actually had time to return something.

通常我使用一些防御性代码解决它,即:

Usually I solve it with some defensive code, i.e:

Template.chartEditPreview.rendered = function () {
  if(this.data)
    drawChart(".chart-container", this.data);
  // else do nothing until the next deps change
}

这不是那么干净,因为我知道这个正确解决问题的唯一方法。

Of course this is not as clean as it should be, but as far as I know the only way to solve problems like this properly.

更新的答案
在这种情况下,我们需要一个依赖关系来触发数据更改时重新运行。铁路由器为我们解决这个问题:

Updated answer In this case we need a dependency to trigger rerun on data change. Iron router solves this for us:

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
}

这篇关于正确加载Template.templateName.rendered数据上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆