2

I am trying to make a pie chart in Meteor but I can't get the template to see the data. This is my code:

PieData = new Mongo.Collection("piedata")

if (Meteor.isClient) {
  Meteor.subscribe('piedata');

  console.log(PieData.find({}).fetch());

  Template.piechart.rendered = function () {
    $('#pie').epoch({
      type: 'pie',
      data: ### Data here (a list) ###
  });
  }
}

if (Meteor.isServer) {
  Meteor.publish('piedata', function() {
    return PieData.find({});
  });
}

I tried PieData.find({}) and even PieData.find({}).fetch() but it just returns an empty list (same with the console.log call). If I run PieData.find({}).fetch() in the dev tools console the data is returned correctly.

elyase
  • 39,479
  • 12
  • 112
  • 119

3 Answers3

2

The reason why this might be happing is that the data (this.data) context provided inside rendered function is not reactive.

On Meteor 0.8.3 ( and maybe some other versions) there is an unofficial way of getting the data reactively, you have to dig into Meteor's source code to find it.

 Template.piechart.rendered = function () {
     this.autorun(function () {

         //This is going to set a dependency
         var myData = Blaze.getCurrentData();
         //your code goes below
     }
 }

Use it at your own risk.

On Meteor 1.0 (as far as I know) there's is an official documented way. You use Template.currentData() https://docs.meteor.com/#/full/template_currentdata

I personally used the rendered function to create things like charts, etc. It's the kind of stuff that you only create once but you got to be very very careful about it.

Let's say you that in your application you have a list on the left and a main content area. On the list you can select different sets of data and when you click, the main content area gets loaded with your chart. Cool, it's working! But wait...

If you click on more items on the left side list, you notice that the page is getting slower. If you create your chart every single time you change the data content, your application is going to suffer and the UI gets frozen for some seconds. In my personal experience, I has this issue with a simple datetime picker. It's very common when the data context changes that the dependent functions will run more than once.

Solution:

 Template.piechart.rendered = function () {
     this.autorun(function (computation) {

         //This is going to set a dependency
         var myData = Template.currentData()

         if (computation.firstRun) {
             //create your pie chart, etc.
         }
         else{
            //update the element(s) data that you create on first run
         }

     }
 }
Mário
  • 1,603
  • 14
  • 24
1

Looks like yo're using autopublish, and the subscription wasn't ready yet.

See my answer on waiting for subscriptions to load.

Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
  • Thats probably the issue but I can't get it working. I did what you recommend but still see an empty list inside `Template.piechart.rendered`. Any ideas? – elyase Nov 08 '14 at 01:31
1

This is hacky solution I had before using Mario's. So I need to wait for 2 conditions:

  1. The template is rendered
  2. The data is ready

So I used two variables for this:

Meteor.subscribe('piedataLoaded', function onReady() {
  Session.set('dataLoaded', true);
});

Template.piechart.rendered = function () {
  Session.set('piechartRendered', true);
}

Finally:

Meteor.autorun( function(computation) {
    if( Session.get('piechartRendered') && Session.get('piedataLoaded')) {
        $('#pie').epoch({
          type: 'pie',
          data: PieData.find({}).fetch()
        });
        computation.stop(); //Stop autorun
    }
});
elyase
  • 39,479
  • 12
  • 112
  • 119