Arash Saidi
Arash Saidi

Reputation: 2238

Meteor onRendered function and access to Collections

When user refresh a certain page, I want to set some initial values from the mongoDB database.

I tried using the onRendered method, which in the documentation states will run when the template that it is run on is inserted into the DOM. However, the database is not available at that instance?

When I try to access the database from the function:

Template.scienceMC.onRendered(function() {
    var currentRad = radiationCollection.find().fetch()[0].rad;
}

I get the following error messages:

Exception from Tracker afterFlush function:
TypeError: Cannot read property 'rad' of undefined

However, when I run the line radiationCollection.find().fetch()[0].rad; in the console I can access the value?

How can I make sure that the copy of the mongoDB is available?

Upvotes: 1

Views: 1051

Answers (3)

Arash Saidi
Arash Saidi

Reputation: 2238

The best way for me was to use the waitOn function in the router. Thanks to @David Weldon for the tip.

Router.route('/templateName', {
    waitOn: function () {
        return Meteor.subscribe('collectionName');
    },
    action: function () {
        // render all templates and regions for this route
        this.render();
    }
});

Upvotes: 1

thatgibbyguy
thatgibbyguy

Reputation: 4113

I can't see your collection, so I can't guarantee that rad is a key in your collection, that said I believe your problem is that you collection isn't available yet. As @David Weldon says, you need to guard or wait on your subscription to be available (remember it has to load).

What I do in ironrouter is this:

data:function(){
    var currentRad = radiationCollection.find().fetch()[0].rad;
    if (typeof currentRad != 'undefined') {
        // if typeof currentRad is not undefined
        return currentRad;
    }
}

Upvotes: 0

Billybobbonnet
Billybobbonnet

Reputation: 3226

You need to setup a proper publication (it seems you did) and subscribe in the route parameters. If you want to make sure that you effectively have your data in the onRendered function, you need to add an extra step.

Here is an example of how to make it in your route definition:

this.templateController = RouteController.extend({
    template: "YourTemplate",

    action: function() {
        if(this.isReady()) { this.render(); } else { this.render("yourTemplate"); this.render("loading");}
        /*ACTION_FUNCTION*/
    },

    isReady: function() {


        var subs = [
            Meteor.subscribe("yoursubscription1"),
            Meteor.subscribe("yoursubscription2")
        ];
        var ready = true;
        _.each(subs, function(sub) {
            if(!sub.ready())
                ready = false;
        });
        return ready;
    },   
    data: function() {
        return {
            params: this.params || {}, //if you have params
            yourData: radiationCollection.find()
        };
    }
});

In this example you get,in the onRendered function, your data both using this.data.yourData or radiationCollection.find()

EDIT: as @David Weldon stated in comment, you could also use an easier alternative: waitOn

Upvotes: 0

Related Questions