1

I'm having a little trouble returning and displaying tags that I'm adding to a subdocument. I have no problem adding tags, but want to put a label on the item for each tag. I simply can't find a resource that helps me return the items in an array within a subdocument. I think it's all the helper where I'm stuck - basically the syntactically correct way to write "Items.(this._id).itemTags.find();" :)

Oh - and I've cut out a lot of the HTML and JS, but, yes, everything else is working fine. The collection is "Items" and the subdocument is "itemTags", set with "itemTags: []" during the insert. In my test environment I can add "Cats" and "Dogs" as tags and can verify it works by inspecting the objects through "Items.find().fetch();" but am struggling to display them.

HTML:

<template name="item">
  {{#each itemTags}}
    <span class="label label-default">{{itemTag}}</span>
  {{/each}}
</template>

JS:

Template.item.helpers({
   itemTags: function() {
    var currentUserId = Meteor.userId();
    return Items.find(); // yes, this line is completely wrong, but I'm lost hehe
  }
});

Template.item.events({
  'submit .add-tag': function(event) {
    event.preventDefault();

    var itemTag = event.target.text.value;

    Items.update(this._id, {$push: {itemTags: itemTag}});

    event.target.text.value = "";

    return false;
  }
});

Database schema (as shown by my insert command):

var item = {
  itemText: $(e.target).find('[name=itemText]').val(),
  createdAt: new Date(),
  createdBy: currentUserId,
  hard: false,
  difficulty: 'easy',
  checked: false,
  itemTags: [],
};

item._id = Items.insert(item);

2 Answers2

2

Your only problem is trying to iterate a cursor and a sub array within the same each block. If you separate your items template and an individual item template, you'll end up with your desired result.

For the sake of simplification, I altered your code to look like this:

This is your main body:

<body>
    {{> items}}
</body>

<template name="items">
  {{#each items}}
    {{> item}}
  {{/each}}
</template>

<template name="item">
  <h2>{{itemText}} tags are:</h2>
  <ul>
  {{#each itemTags}}
    <li>{{this}}</li>
  {{/each}}
  </ul>
</template>

And this is your helper:

Template.items.helpers({
  items: function () {
    return Items.find();
  }
})

Assuming an item document looks like:

{ 
  itemText: String,
  itemTags: Array
}

I've created an app on Meteorpad for you to play with:

http://meteorpad.com/pad/BmRQ5fkwWEMBKszJW/SO-27951102

you can further alter the code there and see the changes in realtime. It is basically jsfiddle for meteor.

Edit: inspired by @chip-castle's comment, you can in fact use a single template with nested each blocks:

<template name="items">
  {{#each items}}
    <h2>{{itemText}} tags are:</h2>
    <ul>
    {{#each itemTags}}
      <li>{{this}}</li>
    {{/each}}
    </ul>
  {{/each}}
</template>

But using separate templates is more flexible in both design and handling events where necessary.

Serkan Durusoy
  • 5,447
  • 2
  • 20
  • 39
  • Wow - thanks! Turns out it wasn't the template helper being incorrectly written. It needed to be deleted altogether, as I already had a template helper on my items template pulling the returns. After deleting that helper and changing to {{this}} it works perfectly. Appreciate all the help! – Erik Johnson Jan 15 '15 at 01:40
  • No problem, glad you've worked it. In theory, you can just print an array on the page as {{itemTags}} and in the background, its toString() method gets returned, so values separated by commas. But then there is no way to provide a dom (like lists) or style them individually, or events etc. Anyway, good lock on the whole proect! :) – Serkan Durusoy Jan 15 '15 at 09:02
0

Do you have a publication and subscription setup?

server/publications.js

Items = new Mongo.Collection("items");

Meteor.publish("items", function () {
  return Items.find({});
});

client/subscriptions.js

Items = new Mongo.Collection("items");

Meteor.subscribe("items");
Chip Castle
  • 2,132
  • 3
  • 20
  • 34
  • Yup, I was able to see all my items and manipulate them with their modification functionality, but I simply couldn't get the tags to appear on them. – Erik Johnson Jan 15 '15 at 01:41