meteorjs iron-router waitOn and using as data on rendered
Asked Answered
D

4

11

I try to get the returned data in my Template.rendered function.

The current code is:

this.route('editCat', {
    layoutTemplate : 'layoutCol2Left',
    template : 'modCategoriesEdit',
    path : '/mod/categories/edit/:_id',
    yieldTemplates : _.extend(defaultYieldTemplates, {
    'navigationBackend' : {to : 'contentLeft'} 
    }),
    waitOn : function () {
         return Meteor.subscribe('oneCat', this.params._id);
    },
    data : function () {
         return Categories.findOne({_id : this.params._id});
    }
 });

In this block i wait on the subscribtion of the Collection Document and return the Document as data.

Now i can use the returned Document in my Template like this:

<template name="modCategoriesEdit"> 
    <h1>Edit {{name}}</h1>
</template>

My problem is that i have to use the returned data in my rendered function like this:

Template.modCategoriesEdit.rendered = function () {
    console.log(this.data);
}

But this returns "null".

So my question is: How is it possible to get access to the returned data in the rendered function ?

Dyedinthewool answered 10/5, 2014 at 0:14 Comment(0)
D
14

Solution:

Just add the following to your iron-router route() method.

action : function () {
    if (this.ready()) {
        this.render();
    }
}

Than the Template will rendered after all is loaded correctly.

Dyedinthewool answered 10/5, 2014 at 0:50 Comment(4)
To improve your solution, you can also add an else{ this.render('YouLoadingTemplate') }Ferrocene
I thought that is what waitOn did. Strange.Fechner
I thought this also! Because of this I was wondering that no data is availabe in my templateDyedinthewool
so if this isn't what waitOn does, what DOES waitOn do?Mllly
S
10

There are 3 solutions if you want to wait until the waitOn data is ready before rendering:

1- Add an action hook to each route

Router.map(function() 
    {
    this.route('myRoute', 
        {
        action: function() 
            {
            if (this.ready())
                this.render();
            }
        }
    }

2- Use the onBeforeAction hook globally or on every route

Sample code for the global hook:

Router.onBeforeAction(function(pause) 
    { 
    if (!this.ready())          
        {
        pause(); 
        this.render('myLoading');
        }
    });

myLoading (or whatever name) must be a template you have defined somewhere.

Don't forget the this.render line, otherwise the problem will occur when leaving the route (while the original problem occurs when loading the route).

3- Use the built-in onBeforeAction('loading') hook

Router.configure(
    {
    loadingTemplate: 'myLoading',
    });

Router.onBeforeAction('loading');   

myLoading (or whatever name) must be a template you have defined somewhere.

Swanner answered 2/6, 2014 at 13:14 Comment(0)
S
3

Using the action hook to check for this.ready() works, but it looks like the official way to do this is to call the following:

Router.onBeforeAction("loading");

Reference: https://github.com/EventedMind/iron-router/issues/679

Sultana answered 5/6, 2014 at 23:40 Comment(0)
B
3

Like @Sean said, the right solution is to use a loading template:

Router.onBeforeAction("loading");

But if you don't want it, like me, I came up with this solution:

Template.xxx.rendered = function() {
    var self = this;

    this.autorun(function(a) {
        var data = Template.currentData(self.view);
        if(!data) return;

        console.log("has data! do stuff...");
        console.dir(data);
        //...
    });
}

Template.currentData is reactive, so in the first time it is null and in the second it has your data.

Hope it helps.

-- Tested on Meteor v1.0 with Iron Router v1.0

Biometry answered 25/11, 2014 at 6:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.