Search code examples
javascriptmongodbmeteoriron-router

How do you render multiple templates with one route controller using iron-router?



Background:

I am making a blog using meteor and iron-router. I want to use a single controller for several different "category pages," which filter a list a blog articles in the yield region.

The Problem:

The article list does not get rerendered when the URL changes. I.e. the article list is not reactive. Interestingly, if I navigate back to the home page, the correct article list shows up.

The Question:

How do I make that article list change when I change between different routes on the category route controller?


Some example code:

Please note that the code for this whole project is available here.

Here is my Route Controller:

CategoryController = RouteController.extend({
    action: function(){
        this.render();
    },
    template: 'category',
    data: function(){
        return {category: this.params.category};
    }
});

CategoryController.helpers({
    articles: function(){
        return Articles.find({category: this.params.category});
    }
});

And here is the template it is rendering:

<template name='category'>
    <div class="container">
        <h2>{{category}}:</h2>
        <ul>
            {{#each articles}}
                <li>
                {{#linkTo route="article.show"}}
                    {{title}}
                {{/linkTo}} 
                </li>
            {{/each}}
        </ul>
    </div>
</template>

Resources/Updates:


Solution

  • The article list does not change because the Template helper is not using a reactive data source. You may use the RouteController.getParams method to establish a reactive dependency on route parameters as shown below.

    CategoryController.helpers({
        articles: function(){
            var controller = this;
            var params = controller.getParams();
    
            return Articles.find({category: params.category});
        }
    });
    

    From Iron Router documentation:

    Note: If you want to rerun a function when the hash changes you can do this:

    // get a handle for the controller.
    // in a template helper this would be
    // var controller = Iron.controller();
    var controller = this;
    
    // reactive getParams method which will invalidate the comp if any part of the params change
    // including the hash.
    var params = controller.getParams();
    

    By default the router will follow normal browser behavior. If you click a link with a hash frag it will scroll to an element with that id. If you want to use controller.getParams() you can put that in either your own autorun if you want to do something procedural, or in a helper.