1
votes

I've run into this problem a few times, and it's slowly driving me insane. Short question: When given a collection which contains an Object as a field, how can we iterate over that object in a template.

Each entry in the collection can look like this:

{
    "_id" : "jsWmXTvocbSMM5JAF",
    "userId" : "gcko4Eo3YtZaWa8aj",
    "gameId" : "eduzNj8kWv7TdiEuE",
    "scores" : {
        "team1" : 3,
        "team2" : 1,
        "losses" : 7
    }
}

We can easily access {{userId}} or {{gameId}} in the template, but of course {{scores}} just displayed [object Object], which we expected.

I tried using {{#each scores}}, which I have used with arrays before, but of course, that throws an error:

{{#each}} currently only accepts arrays, cursors or falsey values.

Then I tried to be clever (rarely a good idea) and push a bunch of Objects into an array, and then return that to the template:

Template.scorePad.helpers({
    scoresArray: function () {
        var arr = [], scores = this.scores;
        for (var key in scores) {
            var obj = {};
            obj[key] = scores[key];
            arr.push(obj);
        }
        return arr;
    }
}

I'm not sure why I thought that would be a good idea, because this just supplies the template with an array looking like this:

[{team1: 3}, {team2: 1}, {losses: 7}]

Which, yeah, great.. I can #each over it, but it just prints out object Object three times. As expected. But here I am, covering all the bases.

There is an open issue about this (regarding not being able to use @key with #each) at the Meteor github, but I'm really hoping someone has a simple solution.

This question is sort of close to what I'm doing, but not at all the same.

I also tried #with, with basically the same results.

Basically, I'm looking for an elegant "Meteor" way of doing this, if one even exists. Clearly I'm not an expert. So what do?

EDIT to answer the comments: To clarify, in the template the ideal solution (which doesn't work) would be use something like this in my html, and iterate over each key:value pair inside scores in the collection data:

<div> {{#each scores}} {{this.key}} {{this.value}} {{/each}} </div>

and iterate over each key:value pair inside scores in the collection data.

1
Pretty sure meteor can just use the . dot operator to get at children within an object. So from an instance to the root of an object, you can do {{myObj.childObj}}.mariocatch
my apologies..you are correct so far in your approach..can you simplify what exactly you are trying to do? I mean some codes and what you are trying to achieve..an example will be fine with your expect outputrepzero
I left an edit at the bottom with more clarification of what I expect output. Hopefully that helps? @mariocatch, the object doesn't actually appear as an object in the template, it appears as a string. II don't think it would actually work in this case anyway because there are an invariable amount of teams, and the keys will actually be team names (like "bobTeam" or "silverBullet") so I can't call the keys by name in the template.inconsiderate

1 Answers

0
votes

Can you try this:

Template.scorePad.helpers({
scoresArray: function () {
    var arr = [], scores = this.scores;
    for (var key in scores) {
        var obj = {};
        obj.key = key;
        obj.value = scores[key];
        arr.push(obj);
    }
    return arr;
  }
}

And iterate it like this:

<div>
{{#each scores}}
    {{this.key}}
    {{this.value}}
{{/each}}
</div>