Search code examples
meteorspacebars

Template helper crashing app


My app is crashing my browser after implementing this columnWidth helper method. All I'm trying to do is rotate between col-md-7 and col-md-5 (Bootstrap classes) so that no two consecutive posts are the same width.

columnWidth: function() {
    if (Session.get('columnWidth') === 'col-md-7') {
        Session.set('columnWidth', 'col-md-5');
    } else {
        Session.set('columnWidth', 'col-md-7');
    }

    return Session.get('columnWidth');
}

The post template:

{{#each this}}
    <div class="{{columnWidth}}">
        <a href="/a/{{url}}"><img src="{{image}}" height="350" width="{{imageWidth}}" alt=""></a>
        <div class="content">
            <h2><a href="/a/{{url}}">{{title}}</a></h2>
            <p>{{content}}</p>
            <span class="dateAuthored">{{date}}</span>
        </div>
    </div>
{{/each}}

this refers to:

data: function() {
    return Articles.find();
}

Any ideas why this is happening? I'm not receiving any errors. The browser tab just becomes unresponsive. Thanks.


Solution

  • You are constantly setting the same reactive variable so for example with the first div when the helper is called it will set it to col-md-7, then when it is called for the 2nd row you are changing the same variable to col-md-5 which is problematic for 2 reasons:

    a) the template will redraw the first column and so they will both be col-md-5

    b) the same helpers will get called again. I believe your browser crashes because you have created an infinite loop. Try console logging something inside your columnWidth helper and see how many times it gets called.

    To achieve what you want you need to get the index of the {{#each }} loop and then have the column class dependent on whether it's odd or even. Unfortunately getting the index in meteor handlebars is a little tricky.

    Try:

    {{#each articles}}
        <div class="{{columnWidth index}}">
            <a href="/a/{{url}}"><img src="{{image}}" height="350" width="{{imageWidth}}" alt=""></a>
            <div class="content">
                <h2><a href="/a/{{url}}">{{title}}</a></h2>
                <p>{{content}}</p>
                <span class="dateAuthored">{{date}}</span>
            </div>
        </div>
    {{/each}}
    

    Then the following helpers:

    articles: function() {
      //'this' in this context should work. 
      //if not just replace with Articles.find().map(...
      var articles = this.map(function(article, index) {
        var i = _.extend(article, {index: index});
        return i;
      });
      return articles;
    },
    columnWidth: function(index) {
      if (index % 2 === 0)
        return "col-md-5";
      else
        return "col-md-7"
    }