Reputation: 1061
I have an array of objects that I am trying to display in categories using bootstrap panels. To get all of the different categories in the array I created a helper that loops through the array and returns an array of strings which contains all the different distinct categories.
Here are my two helpers:
Handlebars.registerHelper("GetFamilies", function (array) {
var families = [];
for (var i = 0; i < array.length; i++) {
var item = array[i];
if (families.indexOf(item.Family) <= -1) {
families.push(item.Family);
}
}
console.log("====================Families");
console.log(families);
return families;
});
Handlebars.registerHelper("GetFamiliyPieces", function (array, familyName) {
var result = _.filter(array, function (obj) {
// return true for every valid entry!
return obj.Family == familyName;
});
console.log("====================Family Pieces");
console.log(result);
return result;
});
Here is the html:
<div class="panel-group" id="toolbox-accordion">
{{#GetFamilies pieces}}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#toolbox-accordion" href="#{{this}}">
{{this}}
</a>
</h4>
</div>
<div id="{{this}}" class="panel-collapse collapse in">
<div class="panel-body">
{{#GetFamilyPieces pieces this}}
<div class="toolbox_item" data-type="{{TypeName}}" data-type-id="{{TypeID}}" title="{{TypeDescription}}" data-input-count="{{Length Inputs}}" data-output-count="{{Length Outputs}}">
<span id="line"></span>
<div class='typename'>{{ShortName TypeName}}</div>
</div>
{{/GetFamilyPieces}}
</div>
</div>
</div>
{{/GetFamilies}}
</div>
In the Console I am hitting the GetFamilies Helper:
But not hitting the GetFamilyPieces helper.
My rendered HTML looks like this:
<div id="toolbox-container">
<div class="panel-group" id="toolbox-accordion">
Circuit,Component,Conductor </div>
</div>
As you can see it is just rendering a comma delimited string of what the array contains. Do you know why the full html is not being rendered?
Upvotes: 1
Views: 2788
Reputation: 9003
You are getting the comma-delimited string because that is the result when an array in JavaScript is .toStringed.
From MDN:
For Array objects, the toString method joins the array and returns one string containing each array element separated by commas.
This means that ["Circuit", "Component", "Conductor"].toString()
results in "Circuit,Component,Conductor"
.
The reason why the rest of your template is not rendered after calling your helper is because your helper is not written properly. Your Block Helper should return a string containing the HTML that is to be rendered. Because your helper returns an array, the toString()
of that array is rendered. In order to access the inner template of a Block Helper, Handlebars provides a function, options.fn
, to which you pass context data object. Your helpers must pass each item in the array argument to the options.fn
function and join the results. A working implementation would look something like the following:
Handlebars.registerHelper("GetFamilies", function (array, options) {
return array
.reduce((memo, el) => {
if (memo.indexOf(el.Family) === -1) {
memo.push(el.Family);
}
return memo;
}, [])
.reduce((memo, family) => memo += options.fn(family), '');
});
Handlebars.registerHelper("GetFamilyPieces", function (array, familyName, options) {
return array
.filter(el => el.Family === familyName)
.reduce((memo, el) => memo += options.fn(el), '');
});
Please note that within your #GetFamilies
Block Helper, pieces
does not necessarily exist within your context data. You must tell Handlebars that to step up a context frame to find pieces
with a path: ../pieces
.
An alternative solution, and, judging by your helpers, the one it looks like you were aiming for, would be to use a standard (non-Block) Handlebars Helper. This would allow you to return the arrays from your helpers as you were doing, and then pass the resulting array to the existing #each
Block Helper. Your template would need to be changed to the following:
{{#each (GetFamilies pieces)}}
{{#each (GetFamilyPieces ../pieces this)}}
{{/each}}
{{/each}}
Upvotes: 6