Collection not available onRendered when using flow-router [solved]

So, I’ve been banging my head all morning trying to figure this out and now it is time to get some help.

I am trying to create a chart using the chart.js package. Here is my code for my template.js in the client folder

Template.visualize.onRendered(function() {
    var age = Questions.find({},{"age": "45-55"}).count();
    alert(age); // returns 0 but there are values and should return a pos int
    showAgeGroups();
});

// Following code block does not work.
Template.visualize.onCreated(function() {
    var self = this;
    self.subscribe("results");
});

function showAgeGroups() {  
    var data = [
        {
            //value: Questions.find({"age": "35-45"}).count(),
            value : 3,
            color: "green"
        },
        {
            value: Questions.find({"age": "45-55"}).count(),
            color: "red"
        },
        {
            value: Questions.find({"age": "Over 55"}).count(),
            color: "yellow"
        }
    ];
    var ctx = $("#age-groups").get(0).getContext("2d");
    var ageChart = new Chart(ctx);
    new Chart(ctx).Pie(data);
}

If I hard code the values like I did for the “35-45” age group, the chart shows up but shows 100% for 3 and nothing for anything else even though there are values there.

My route.js in the lib folder

FlowRouter.route("/visualize", {
    subscriptions : function(params, queryParams){
        this.register("questions", Meteor.subscribe("results"));
    },

    action: function (params) {
        BlazeLayout.render("visualize");
    }
});

My publish.js in the server folder

Meteor.publish("results", function(){
    return Questions.find({});
});

Any help in the right direction to the solution will be much appreciated!

Thanks in advance.

Kamal

Your showAgeGroups function is running before your subscription is ready. Try putting your template subscription into an autorun function as outlined in the FlowRouter documentation: https://kadira.io/academy/meteor-routing-guide/content/subscriptions-and-data-management/with-blaze

Your code should look like this:

Template.visualize.onCreated(function() {
    var self = this;
    self.autorun(function() {
        self.subscribe("results");
    }
});

Also, since your subscription is now reactive, maybe change your onRendered function to account for that:

Template.visualize.onRendered(function() {
    var age = Questions.find({},{"age": "45-55"});
    
    if (age) {
        alert(age.count()); 
        showAgeGroups();
    }
});
2 Likes

Thanks, eterps, but it did not work. I even tried the following

Template.visualize.onCreated(function() {
    var subs = new SubsManager();
    var self = this;
    self.ready = new ReactiveVar();
    self.autorun(function () {
        var handle = subs.subscribe("results");
        self.ready.set(handle.ready());
    });
});

from https://kadira.io/academy/meteor-routing-guide/content/subscriptions-and-data-management/using-subs-manager and still no luck

OK, I got it to work with the following

Template.visualize.onCreated(function() {
    var self = this;
    self.autorun(function () {
            self.subscribe("results", function(){
                showAgeGroups();
        });
    });
});

The onRendered method was not necessary(?) so I deleted it.

My new challenge is that even though the chart shows up properly, it is not reactive, i.e. will not update when new data is put into the database. Any suggestions?

Here is how to update the chart reactively

Template.visualize.onRendered(function() {
   Questions.find().observeChanges({
        added: function(){
            showAgeGroups();
        }
    });
});

Also, the onCreated method can be simplified to this:

Template.visualize.onCreated(function() {
    var self = this;
    self.subscribe("results", function(){
        showAgeGroups();
    });
});

There seems to be bug where the chart starts freaking out on mouse-over when using observerChanges. I’ve file a bug report (https://github.com/MeteorPackaging/Chart.js/issues/3).

Hope this is helpful to someone else in my position.

If my way is incorrect and there is a better way, I’d love to know that.

Kamal

The main concept with onCreated/onRendered is that you should wait for sub is ready and then do the render. So you can separate that logic into 2 steps:

(coffee)

Template.visualize.onCreated ->
  self = @
  self.sub = Meteor.subscribe('results')

Template.visualize.onRendered - >
  self = @
  ctx = self.find('canvas').getContext('2d')
  self.chart = new Chart(ctx)
  self.autorun - >
    if(self.sub.ready())
      data = <...>
      self.chart.Pie(data)

Template.visualize.onDestroyed ->
  @sub.stop()
1 Like

This could be called multiple times. Not when all the chart data is ready!

1 Like

@mrzfod Thanks! That really helps. The chart is still jittery on mouse over and shows incorrect data but not as schizophrenic as it was with my code.
It also redraws the entire chart when data is added to the collection.

I’m having the same problem with jittery chart.js. I posted my problem over here: http://stackoverflow.com/questions/35103925/hovering-over-chart-js-values-in-meteor-onrendered-function-causes-chart-axis-sh