0

Session.set('coursesReady', false); on startup.

UPDATE:

I made it into a simpler problem. Consider the following code. Inside router.js

Router.route('/', function () {
  Meteor.subscribe("courses", function() {
    console.log("data ready")
    Session.set("coursesReady", true);
  });
}

and inside main template Main.js

  Template.Main.rendered = function() {
    if (Session.get('coursesReady')) {
      console.log("inject success");
      Meteor.typeahead.inject();
    }

The message "inject success" is not printed after "data ready" is printed. How come reactivity does not work here?

Maximus S
  • 10,759
  • 19
  • 75
  • 154

2 Answers2

1

Reactivity "didn't work" because rendered only executes once (it isn't reactive). You'd need to wrap your session checks inside of a template autorun in order for them to get reevaluated:

Template.Main.rendered = function() {
  this.autorun(function() {
    if (Session.get('coursesReady')) {
      console.log("inject success");
      Meteor.typeahead.inject();
    }
  });
};

Probably a better solution is to wait on the subscription if you want to ensure your data is loaded prior to rendering the template.

Router.route('/', {
  // this template will be rendered until the subscriptions are ready
  loadingTemplate: 'loading',

  waitOn: function () {
    // return one handle, a function, or an array
    return Meteor.subscribe('courses');
  },

  action: function () {
    this.render('Main');
  }
});

And now your rendered can just do this:

Template.Main.rendered = function() {
  Meteor.typeahead.inject();
};

Don't forget to add a loading template.

David Weldon
  • 63,632
  • 11
  • 148
  • 146
  • Where do I include `Meteor.typeahead.inject();` in this case? I attempted using `waitOn` a few times, but it seemed `waitOn` always needs `Meteor.subscribe('courses');` to be returned. In addition, I am really curious why reactivity wouldn't work in this case regardless of the subscription issue. – Maximus S Apr 06 '15 at 02:35
  • If I only have on subscription, is `waitOn` better/faster than using a callback function inside `subscribe('some_data', callback)`? I am having some performance issues described in my other question, http://stackoverflow.com/questions/29466051/how-to-debug-performance-issue-optimize-your-meteor-app – Maximus S Apr 06 '15 at 06:47
  • Given that the number of documents you have is unusually high (that's a topic for your other question), I'd say it's going to take a long time no matter what you do. The answer depends on what your UX should be. If it's important that the user see the page quickly but not see data, I'd suggest using a [template subscription](https://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe). If it would be better for the user to see a loading page, stick with the `waitOn`. – David Weldon Apr 06 '15 at 14:08
0

To Solve Your Problem

Template.registerHelper("course_data", function() {
    console.log("course_data helper is called");    
    if (Session.get('coursesReady')) {
      var courses = Courses.find().fetch(); 
      var result = [ {                         **Changed**
          name: 'course-info1',
          valueKey: 'titleLong',
          local: function() {
            return Courses.find().fetch();
          },
          template: 'Course'
        }];
        Session.set('courseResult', result);   **New line**
        return Session.get('courseResult');    **New line**
      ,

Explanation

The answer is at the return of the helper function needs to have be associated with reactivity in order for Blaze, template renderer, to know when to rerender.

Non-reactive (Doesn't change in the DOM as values changes)

Template.Main.helpers({
    course_data: UI._globalHelpers.course_data    ** Not reactive
  });

Essentially: UI._globalHelpers.course_data returns an array of objects which is not reactive:

return [
        {
          name: 'course-info1',
          valueKey: 'titleLong',
          local: function() {
            return Courses.find().fetch();
          },
          template: 'Course'
        },

Reactive

From Meteor Documentation: http://docs.meteor.com/#/full/template_helpers

Template.myTemplate.helpers({
  foo: function () {
    return Session.get("foo");   ** Reactive
  }
});

Returning Session.get function to Blaze is reactive; thus, the template will change as the values changes.

wuguay
  • 11
  • 1