Meteor client side collection needs to have all data populated before anything else

StackOverflow https://stackoverflow.com/questions/23198752

  •  07-07-2023
  •  | 
  •  

Вопрос

I'm trying to use a client side collection as a site configuration system. I insert documents representing my different pages, and the iron-router and navigation tabs all use them to determine what pages they are and what templates are represented by them. Each page uses a {{> contentTemplate}} inclusion helper to load it's relevant template.

It all works great, when the data has all loaded. When I restart the app on certain pages, the data hasn't loaded yet, and I receive the Exception from Deps recompute function: Error: Expected null or template in return value from inclusion function, found: undefined error.

Here's my javascript:

StoriesArray = [
{ category: 'teaching', contentTemplate: 'teachingHome', title: 'Teaching Home'},
...
];

Stories = new Meteor.Collection(null);
StoriesArray.forEach(function (story, index) {
    story._id = index + '';
    Stories.insert(story);
});

// in main.js
Template.teachingPost.contentTemplate = function() {
    console.log(this);
    console.log(this.contentTemplate);
    return Template[this.contentTemplate];
};

// in router.js
this.route('teaching', {
    layoutTemplate: 'teachingPost',
    data: function() { return Stories.findOne({contentTemplate: 'teachingHome', category: 'teaching'}); }
});

The console logs in the contentTemplate helper above log twice, the first time as this:

Object {} main.js?1f560c50f23d9012c6b6dd54469bb32b99aa4285:45

undefined main.js?1f560c50f23d9012c6b6dd54469bb32b99aa4285:46

and the second time as this:

Object {category: "teaching", contentTemplate: "teachingHome", title: "Teaching Home"} main.js?1f560c50f23d9012c6b6dd54469bb32b99aa4285:45

teachingHome main.js?1f560c50f23d9012c6b6dd54469bb32b99aa4285:46

so the router is simply trying to load this data too early.

I've tried putting the StoriesArray loading process into different files all over my app, including lib, and even tried putting it into Meteor.startup, but it's always the same result.

The normal iron-router waitOn/subscription pattern doesn't really apply here, since this is a client side collection built with null, that has no server representation. I don't want this to have server representation, because this is static content that there's no need to go to my server for.

How do I ensure this information is done before continuing?

Это было полезно?

Решение

Untested, but per Iron Router's docs on waitOn:

Returning a subscription handle, or anything with a ready method from the waitOn function will add the handle to a wait list.

Also in general it's better to use find with data, rather than findOne, as find will return an empty cursor when the collection is empty as opposed to findOne returning undefined. So try this:

// in router.js
this.route('teaching', {
  layoutTemplate: 'teachingPost',
  data: function() {
    return Stories.find({contentTemplate: 'teachingHome', category: 'teaching'});
  },
  waitOn: function() {
    var handle = {};
    handle.ready = function() {
      if (Stories.find().count() !== 0)
        return true;
      else
        return false;
    }
    return handle;
  }
});

And adjust your Template.teachingPost.contentTemplate function to work with a cursor rather than an object.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top