I'm using Handlebars.js and got stuck in a problem I can't solve.
I want to iterate through an array within a template, but the problem is that the expression I'm using for the iterator is a getter and not an array.
A piece of code that illustrates the problem is the following one:
HTML:
<script id="template" type="text/x-handlebars">
Accessing directly: {{array}} <br/>
Accessing by getter: {{getArray}} <br/>
<br/>
Looping directly:
<ul>
{{#each array}}
<li>{{this}}</li>
{{/each}}
</ul>
<br/>
Looping by getter:
<ul>
{{#each getArray}}
<li>{{this}}</li>
{{/each}}
</ul>
</script>
<p id="content"></p>
JS:
var template = Handlebars.compile($("#template").html());
var element = {
array: [0, 1, 2],
getArray: function() {
return this.array;
}
};
$("#content").html(template(element));
The problem is that the each
that uses the getter does nothing. This can be seen in this jsFiddle.
Is there any clean way to perform this using the getter, or should I write a helper or something like an auxiliary function?
Thanks!
{{#each}}
expects an array and it won't understand anything else. You could add a simple custom helper for this, you'd just have to remember to use fn.call(this)
if you expect this:
getArray: function() {
return this.array;
}
to have the right this
. Something like this would probably do the trick:
Handlebars.registerHelper('smart_each', function(a, block) {
if(typeof a == 'function')
a = a.call(this);
var s = '';
for(var i = 0; i < a.length; ++i)
s += block(a[i]);
return s;
});
Demo: http://jsfiddle.net/ambiguous/yuPfD/
You might want to look at the {{#each}}
implementation in the Handlebars source to spruce that up a bit but I'll leave that as an exercise.
If you use proper JavaScript getters, your technique will work. Here's an example using classes, available in ES6. For an ES5 example of the code below, see this version which uses babel.io's repl.
'use strict'
const handlebars = require('handlebars')
const template = "{{#each letters}} {{this}} {{/each}}"
var context
class Alphabet {
get letters() {
return 'abc'.split('')
}
}
context = new Alphabet()
console.log('class instance with getter methods:')
console.log(handlebars.compile(template)(context))
context = {
letters: 'xyz'.split('')
}
console.log('regular object:')
console.log(handlebars.compile(template)(context))
The output:
❯ node index.js
class instance with getter methods:
a b c
regular object:
x y z
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With