Show reactive list from document array after id is created [SOLVED]


#1

Sorry, the topic title is probably confusing. Here is what I am trying to do.

I have two divs in my template. let’s call them div1 and div2. When the page loads div2 is hidden. The user is asked to create a list, with a name and description. Then they click next, at which point the following happens:

  1. A new document is created in the database
  2. A session variable with the document id is set
  3. div1 is hidden and div2 is shown.

In div 2, the user is asked to create list items. The list items are inserted in the document created in div1. I would like to show the list items in div2 in a “ul” as they are added.

Here is my template code right now.

<template name="newListItems">
{{#each items}}
    <li>-- {{this.itemName}}</li>
{{/each}}

and the corresponding javascript.

Template.newListItems.helpers({
 items : function(_currentListId){
  if (_currentListId) {           
   return Lists.find(_currentListId, {fields : {"items.itemName":1, _id:0}});  
  }
 }
});

Unfortunately, this does not display the item names. Any suggestions to help me fix this would be much appreciated. Of course, if I am missing any piece of information that you need, please let me know.

Thanks a bunch in advance for your assistance.

Kamal


#2

It seems you don’t pass the _currentListId parameter when calling the items helper…


#3

what steve said,

you also need to reconcile this.itemName with the actual document you’re querying: {items:{itemName:}}. It will be undefined other wise.

It’s not entirely clear how you’ve structured your data.

My guess is that you have documents with items:[subDoc, …] field … You cannot modify the array field on-query - this is a mongodb limitation with denormalized data. You can match entire documents. You could do {items:1} as your projection, and then iterate through this.items in the template and display the itemNames that way. If you have items:[{itemName:‘bob’}, …] then you can’t just get back [‘bob’, … ] from your query. You need to do the operations on the query afterwards manually


#4

Hi Steve and Streemo,

Thanks for your replies.

Yes, not passing the _currentListId was a problem. Such an obvious mistake that I wasn’t seeing even after staring at the problem for several hours. I am getting there. Still not working though.

Here is my db structure:

"list" : [
  {
     "_id" : "id",
     "author" : "authorId",
     "createdOn" : "DateTime",
     "description" : "description",
     "items" : [
        {
              "itemComplete" : "Boolean",
              "itemName" : "item name",
              "itemDescription" : "item description",
        },
        {
              "itemComplete" : "Boolean",
              "itemName" : "item name",
              "itemDescription" : "item description",
        }
     ],

I’ve tried various iterations of template code, e.g.

{{#each items}}
  <li>-- {{items.itemName}}</li>
{{/each}}

and

{{#each items}}
  <li>-- {{this.items.itemName}}</li>
{{/each}}

with no luck.

My helper function now looks like

Template.newListItems.helpers({
    items : function(_currentListId){
        _currentListId = Session.get("currentListId");
        if (_currentListId) {
            return Lists.find(_currentListId, {items:1});
        }
    }
});

OK, while writing this post, I was trying different things. I discovered this. If I use the following in my template.

{{#each items}}
  <li>-- {{items.[0].itemName}}</li>
{{/each}}

I can get the first “itemName” to show up. If I change 0 to 1, I get the second “itemName,” etc. But only thing at a time, obviously. So, I’m almost there. Any suggestions?


#5

Does this work?

Template.newListItems.helpers({
    items : function(){
        var _currentListId = Session.get("currentListId");
        return _currentListId ? Lists.find(_currentListId, {items:1}).items : [];
    }
});

{{#each items}}
  <li>{{itemName}}</li>
{{/each}}

#6

Hi Steve,

Thanks again for your assistance. Reading your code, I was sure it would work but alas it didn’t. Digging about the intertubes and trying a few different things, I finally got it to work via the following.

Template:

{{#each items.items}}
  <li>{{itemName}}</li>
{{/each}}

[For other newbies like me, the first items in {{#each items.items}} is the items : from the javascript below, and the second items is the array from the JSON database structure.]

Javascript:

Template.newListItems.helpers({
  items : function(){
    _currentListId = Session.get("currentListId");
    if (_currentListId) {
      return Lists.findOne(_currentListId, {fields: {"items": 1}});
    }
  }
});

#7

Sorry, there was (at least) one bug in my code: I wrote find instead of findOne.