0

I have a collection, Ages, which only holds one key: ages.

In it I store an array of strings like so:

['51', '24', '21', '19', '15']

I struggled a bit with how to iterate over it in the template but this is what I found worked. First the HTML:

<template name="ageFilter">
  {{#each age}}
    <li>
      {{this}}
    </li>
  {{/each}}
</template>

And the helper:

Template.ageFilter.helpers({
  age: function() {
    return Ages.findOne().ages
  }
})

This is a rather ugly solution that rests on my having only one object in my database (since I use findOne() but it's not a big problem, and it works. The template iterates over the array and outputs it.

There's only one problem: the browser console throws an error!

Exception in template helper: TypeError: Cannot read property 'ages' of undefined

Why is this and how can I get rid of it?

1 Answer 1

2

Maybe your age helper is first called before subscription to your Ages publication occurs, therefore the first call(s) to Ages.findOne() end(s) up returning nothing. You could check if your Ages document has been fetched correctly:

Template.ageFilter.helpers({
  age: function() {
    var ageItem = Ages.findOne();
    return (ageItem ? ageItem.ages : null);
  }
});

But that's just hacking around the issue. Best approach would be to make sure your template does not get rendered before subscription is done. You could use iron-router and put your subscriptions in waitOn for that. For example:

Router.route('home', {
    path: '/',
    waitOn: function() {
        return Meteor.subscribe('ages');
    }
});

Also, overall you might want to change your design and just put one age value per document in your Ages collection, stored in a key like value or something. It seems more logical. This way you could do:

<template name="ageFilter">
  {{#each ages}}
    <li>
      {{value}}
    </li>
  {{/each}}
</template>

And your helper:

Template.ageFilter.helpers({
  ages: function() {
    return Ages.find().fetch();
  }
});
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer. My subscription gets loaded in Iron Router's `onBeforeAction', sadly out of necessity. (Edit: Actually that was my other subscription, so that would work!) Your last suggestion can't help with this issue, can it? I was on the fence on how to store it, and I'm glad storing it as you said isn't crazy because that would be my preferred method.
Yes, my last suggestion would also solve your displayed console error problem. No ages will be fetched at first, no <li> will be displayed, but no error in the console. Until, of course, your subscription catches up, then your ages will appear automatically :) it should look instantaneous.
Oh, that's a relief, because switching the subscription to waitOn didn't work. :( Is there something inherently wrong about chaining ages on the find()?
Well yes, you should not get a key value directly on a call to some function if you are not sure that this function will return an object. In your case, Ages.findOne() can return either an object or undefined, therefore it is not wise to ask for its ages value right away. Even if you waited for subscription actually! Because you never know if one day your collection will be empty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.