Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a Meteor template that should be displaying some data.

Template.svg_template.rendered = function () {
  dataset_collection = Pushups.find({},{fields: { date:1, data:1 }}, {sort: {date: -1}}).fetch();

  a = moment(dataset_collection[0].date, "YYYY/M/D");
  //more code follows that is also dependent on the collection being completely loaded
};

Sometimes it works, sometimes I get this error:

Exception from Deps afterFlush function: TypeError: Cannot read property 'date' of undefined

I'm not using Deps in any context. As I understand it, the collection is being referenced before it is completely finished loading.

I therefore would like to figure out how to simply say "wait until the collection is found before moving on." Should be straightforward, but can't find an updated solution.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
217 views
Welcome To Ask or Share your Answers For Others

1 Answer

You are right, you should ensure that code depending on fetching the content of a client-side subscribed collection is executed AFTER the data is properly loaded.

You can achieve this using a new pattern introduced in Meteor 1.0.4 : https://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe

client/views/svg/svg.js

Template.outer.onCreated(function(){
  // subscribe to the publication responsible for sending the Pushups
  // documents down to the client
  this.subscribe("pushupsPub");
});

client/views/svg/svg.html

<template name="outer">
  {{#if Template.subscriptionsReady}}
    {{> svgTemplate}}
  {{else}}
    Loading...
  {{/if}}
</template>

In the Spacebars template declaration, we use an encapsulating outer template to handle the template level subscription pattern. We subscribe to the publication in the onCreated lifecycle event, and we use the special reactive helper Template.subscriptionsReady to only render the svgTemplate once the subscription is ready (data is available in the browser). At this point, we can safely query the Pushups collection in the svgTemplate onRendered lifecycle event because we made sure data made its way to the client :

Template.svgTemplate.onRendered(function(){
  console.log(Pushups.find().fetch());
});

Alternatively, you could use the iron:router (https://github.com/iron-meteor/iron-router), which provides another design pattern to achieve this common Meteor related issue, moving subscription handling at the route level instead of template level.

Add the package to your project :

meteor add iron:router

lib/router.js

Router.route("/svg", {
  name: "svg",
  template: "svgTemplate",
  waitOn: function(){
    // waitOn makes sure that this publication is ready before rendering your template
    return Meteor.subscribe("publication");
  },
  data: function(){
    // this will be used as the current data context in your template
    return Pushups.find(/*...*/);
  }
});

Using this simple piece of code you'll get what you want plus a lot of added functionalities. You can have a look at the Iron Router guide which explains in great details these features.

https://github.com/iron-meteor/iron-router/blob/devel/Guide.md

EDIT 18/3/2015 : reworked the answer because it contained outdated material and still received upvotes nonetheless.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...