Given the following JSON:
{
"Colours": [
{ "ColourID": 1, "Name": "Red" },
{ "ColourID": 2, "Name": "Yellow" },
{ "ColourID": 3, "Name": "Blue" }
],
"Sizes": [
{ "SizeID": 1, "Name": "Small" },
{ "SizeID": 2, "Name": "Medium" },
{ "SizeID": 3, "Name": "Large" }
],
"Products": [
{ "ColourID": 1, "SizeID": 1, "Name": "Red Small" },
{ "ColourID": 1, "SizeID": 2, "Name": "Red Medium" },
{ "ColourID": 1, "SizeID": 3, "Name": "Red Large" },
// and so on...
]
}
And the following template HTML:
<table>
{{#Products}}
<tr>
<td>
<input type="text" value="{{Name}}">
</td>
<td>
<select>
{{#Colours}}
<option value="{{ColourID}}">{{Name}}</option>
{{/Colours}}
</select>
</td>
<td>
<select>
{{#Sizes}}
<option value="{{SizeID}}">{{Name}}</option>
{{/Sizes}}
</select>
</td>
</tr>
{{/Products}}
</table>
How can I build the select
boxes using the mon colour/size data from the global context, but for each table row set the selected="selected"
attribute on the options which have values matching the current product's Colour/Size ID?
As it stands, within the loop there is no access to the Colours
or Sizes
arrays, so the selects are blank. I've tried using a global helper to explicitly pass them into each product from the global context before rendering, like so:
Handlebars.registerHelper('productloop', function(context, options) {
var ret = [];
for(var i=0, j=context.Products.length; i<j; i++) {
var option = context.Products[i];
option.Colours = context.Colours;
option.Sizes = context.Sizes;
ret.push(options.fn(option));
}
return ret.join('');
});
And the HTML:
<table>
{{#productloop}}
<tr>
<td>
<input type="text" value="{{Name}}">
</td>
<td>
<select>
{{#Colours}}
<option value="{{ColourID}}">{{Name}}</option>
{{/Colours}}
</select>
</td>
<td>
<select>
{{#Sizes}}
<option value="{{SizeID}}">{{Name}}</option>
{{/Sizes}}
</select>
</td>
</tr>
{{/productloop}}
</table>
Which does work, but it seems very clunky, and I still have no idea how to set the selected
attributes for each product's colour/size select.
Can anyone help me out? I have control over the code which generates the JSON, so the JSON structure can be changed if required.
Given the following JSON:
{
"Colours": [
{ "ColourID": 1, "Name": "Red" },
{ "ColourID": 2, "Name": "Yellow" },
{ "ColourID": 3, "Name": "Blue" }
],
"Sizes": [
{ "SizeID": 1, "Name": "Small" },
{ "SizeID": 2, "Name": "Medium" },
{ "SizeID": 3, "Name": "Large" }
],
"Products": [
{ "ColourID": 1, "SizeID": 1, "Name": "Red Small" },
{ "ColourID": 1, "SizeID": 2, "Name": "Red Medium" },
{ "ColourID": 1, "SizeID": 3, "Name": "Red Large" },
// and so on...
]
}
And the following template HTML:
<table>
{{#Products}}
<tr>
<td>
<input type="text" value="{{Name}}">
</td>
<td>
<select>
{{#Colours}}
<option value="{{ColourID}}">{{Name}}</option>
{{/Colours}}
</select>
</td>
<td>
<select>
{{#Sizes}}
<option value="{{SizeID}}">{{Name}}</option>
{{/Sizes}}
</select>
</td>
</tr>
{{/Products}}
</table>
How can I build the select
boxes using the mon colour/size data from the global context, but for each table row set the selected="selected"
attribute on the options which have values matching the current product's Colour/Size ID?
As it stands, within the loop there is no access to the Colours
or Sizes
arrays, so the selects are blank. I've tried using a global helper to explicitly pass them into each product from the global context before rendering, like so:
Handlebars.registerHelper('productloop', function(context, options) {
var ret = [];
for(var i=0, j=context.Products.length; i<j; i++) {
var option = context.Products[i];
option.Colours = context.Colours;
option.Sizes = context.Sizes;
ret.push(options.fn(option));
}
return ret.join('');
});
And the HTML:
<table>
{{#productloop}}
<tr>
<td>
<input type="text" value="{{Name}}">
</td>
<td>
<select>
{{#Colours}}
<option value="{{ColourID}}">{{Name}}</option>
{{/Colours}}
</select>
</td>
<td>
<select>
{{#Sizes}}
<option value="{{SizeID}}">{{Name}}</option>
{{/Sizes}}
</select>
</td>
</tr>
{{/productloop}}
</table>
Which does work, but it seems very clunky, and I still have no idea how to set the selected
attributes for each product's colour/size select.
Can anyone help me out? I have control over the code which generates the JSON, so the JSON structure can be changed if required.
Share Improve this question edited Aug 29, 2013 at 11:37 Mark Bell asked Aug 29, 2013 at 11:30 Mark BellMark Bell 29.8k26 gold badges121 silver badges150 bronze badges 2- Why doesn't your JSON have double quotes around the property names? – Qantas 94 Heavy Commented Aug 29, 2013 at 11:34
- 1 Because it was formatted that way by a Chrome extension I use and I just copied and pasted it in. Fixed now. – Mark Bell Commented Aug 29, 2013 at 11:38
2 Answers
Reset to default 5You can use ../
to step up one level in the namespace:
<select>
{{#each ../Colours}}
<option value="{{ColourID}}">{{Name}}</option>
{{/each}}
</select>
I also switched to {{#each}}
as I find it more readable when dealing with ../
.
Demo: http://jsfiddle/ambiguous/pFpS4/
Add selected property in your handlebar template for the current product . Eg. for Blue, Small, Red medium...
{
Colours: [
{ "ColourID": 1, "Name": "Red" },
{ "ColourID": 2, "Name": "Yellow" },
{ "ColourID": 3, "Name": "Blue", "selected" : "selected" }
],
Sizes: [
{ "SizeID": 1, "Name": "Small" , "selected" : "selected" },
{ "SizeID": 2, "Name": "Medium" },
{ "SizeID": 3, "Name": "Large" }
],
Products: [
{ "ColourID": 1, "SizeID": 1, "Name": "Red Small" },
{ "ColourID": 1, "SizeID": 2, "Name": "Red Medium", "selected" : "selected" },
{ "ColourID": 1, "SizeID": 3, "Name": "Red Large" },
// and so on...
]
}
And then use that inside your template like following.
<table>
{{#Products}}
<tr>
<td>
<input type="text" value="{{Name}}">
</td>
<td>
<select>
{{#Colours}}
<option value="{{ColourID}}" {{selected}}>{{Name}}</option>
{{/Colours}}
</select>
</td>
<td>
<select>
{{#Sizes}}
<option value="{{SizeID}}" {{selected}}>{{Name}}</option>
{{/Sizes}}
</select>
</td>
</tr>
{{/Products}}
</table>