Is the following helper defined correctly?

Hello,

I am new to meteor, is the following helper defined correctly? I mean should I return something when the if is false using else? For a moment the game document is undefined, is that normal?
How do I exec a function when the game document stops being undefined? I am familiar with promises.

Template.Page_game.helpers({
  isGameStatus(status) {
    let game = Template.instance().getGame();
    if (game) {
      return status == game.status;
    }
  }
});

Also feel free to point out any newbie mistake or pitfall on my Blaze template definition.

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { TAPi18n } from 'meteor/tap:i18n';
import { Games } from '../../../api/games/games.js';

import './game.html';

Template.Page_game.onCreated(function() {
  this.errors = new ReactiveDict();
  this.state = new ReactiveDict();
  this.state.setDefault({
    currentQuestion: 0
  });

  this.getGameId = () => FlowRouter.getParam('id');

  this.autorun(() => {
    this.subscribe('games.getById', this.getGameId());
  });

  this.getCurrentQuestion = () => {
    let id = FlowRouter.getParam('id');
    let game = Games.findOne(id);
    let currentQuestion = this.state.get('currentQuestion');
    return game && game.questions[currentQuestion];
  };

  this.getGame = () => {
    let id = FlowRouter.getParam('id');
    return Games.findOne(id);
  };
});

Template.Page_game.onRendered(function() {
  let game = this.getGame();
  console.log('onRendered', game);
});

Template.Page_game.helpers({
  game() {
    let game = Template.instance().getGame();
    console.log('game', game);
    return game;
  },
  gameURL() {
    let game = Template.instance().getGame();
    if (game) {
      return FlowRouter.url('game', {id: game._id});
    }
  },
  isGameStatus(status) {
    let game = Template.instance().getGame();
    if (game) {
      return status == game.status;
    }
  },
  player1() {
    let game = Template.instance().getGame();
    if (game) {
      return Meteor.users.findOne(game.player1);
    }
  },
  currentQuestionClass(index) {
    let currentQuestion = Template.instance().state.get('currentQuestion');
    return index == currentQuestion && 'btn-primary text-white';
  },
  currentQuestion() {
    return Template.instance().getCurrentQuestion();
  }
});

Template.Page_game.events({
  'click .js-change-question'(event, instance) {
    let index = parseInt($(event.target).data('index'));
    instance.state.set('currentQuestion', index);
  },
  'click #js-solution-btn'(event, instance) {
    let question = instance.getCurrentQuestion();
    $('#js-answer-html input').each((i, input) => {
      $(input).val(question.answerParsed[question.answerHiddenWords[i]]).prop('readonly', true);
    });
  }
});

Yes, this looks correct to me.

Each helper is run in a separate Tracker.autorun, which will keep track of reactive data sources and re-run the helper function when those data sources change.

This this helper function’s case, that means if either FlowRouter.getParam('id') or Games.findOne change, it will re-run.

Normally your page will load before it has data, at which point game is undefined, then when the data is loaded from the server it re-runs with the real data and updates

1 Like