This may be a duplicate question but I've yet to find a solution to my specific problem. I have a db set up like this:
{ "_id" : ObjectId("5c43b0e463ad7e8adfa4f07a"), "name" : "The Box", "price" : "80", "parts" : [ { "pname" : "piccolo", "pprice" : "3" }, { "pname" : "Flute 1", "pprice" : "3" } ] }
Is there a way to iterate through the parts array and do a nested {{#each}} loop so that I can display the name of each document and each part within the name? my code so far:
<tbody>
{{#each pieces}}
<tr class="itemList">
<td class="name">{{name}}</td>
<td class="pdf">PDF</td>
<td class="audio">AUDIO</td>
<td class="format">FORMAT</td>
<td class="price" >${{price}}</td>
<td><input class ="qty" type ="number" name ="quantity" value="0"></td>
</tr>
{{#each parts}}
<tr>
<td colspan="3"></td>
<td class="partName">{{pname}}</td>
<td class="partPrice">{{pprice}}</td>
<td><input class="partQty" type="number" name="quantity" value="0"></td>
</tr>
{{/each}}
{{/each}}
</tbody>
and my helpers:
Template.band.helpers({
pieces: function(){
return bandmusic.find({})
},
parts: function(){
return bandmusic.find({parts})
} })
The first thing to realise is that your parts
helper a) doesn't work and b) isn't what you need anyway.
bandmusic.find({parts})
doesn't mean "return the parts array from documents in the bandmusic collection", which is what you seem to be wanting it to do. {parts}
is ES6 shorthand for {parts: parts}
(see this answer). But your function has no variable parts
- so in your find
, what you're really saying is "find documents which match the condition {parts: undefined}
What you're trying to do with your nested #each
is loop through each document in the database, and then within each document, loop through the parts
array.
Well, you get the documents from your pieces
helper, and each document contains a parts
array, which you can just loop through without needing a helper.
Your code should work if you just delete the parts
helper. Blaze has a lookup order which you can read about here. What this means is that when Blaze sees parts
, it first thinks "is there a helper called parts
?" - which there is, and it's not working, so nothing happens.
But what you want it to think is "Is there a field in the current data context called parts
" - which there is, but helpers
come higher in the lookup order so it never gets there.
So the simplest solution in theory is to remove the helper.
As you can see from the lookup order
link, it's often unclear what refers to what in Spacebars/Blaze. You can make things much clearer by using the syntax described in the Blaze docs for each
Instead of #each array
you should introduce a new variable to refer to the current item in the array - #each item in array
. And then access the item's properties as usual - item.prop1 - item.prop2
So your new code becomes:
{{#each piece in pieces}}
<tr class="itemList">
<td class="name">{{piece.name}}</td>
<td class="pdf">PDF</td>
<td class="audio">AUDIO</td>
<td class="format">FORMAT</td>
<td class="price" >${{piece.price}}</td>
<td><input class ="qty" type ="number" name ="quantity" value="0"></td>
</tr>
{{#each part in piece.parts}}
<tr>
<td colspan="3"></td>
<td class="partName">{{part.pname}}</td>
<td class="partPrice">{{part.pprice}}</td>
<td><input class="partQty" type="number" name="quantity" value="0"></td>
</tr>
{{/each}}
{{/each}}