I am using Handlebars to display comments.
{{#each COMMENTS}}
<div class="heightfix">
<div class="commentIcon"></div>
<label id="commentDate1" class="bold">{{COMMENTON}}</label>:
<label id="commentCreator1" class="bold">{{COMMENTBY_FIRSTNAME}} {{COMMENTBY_LASTNAME}}</label>
<label class="commentContent" id="commenttext_{{ID}}">{{COMMENTTEXT}}</label>
</div>
{{/each}}
In those COMMENTS, I have INDEX. I would like to display the comments as per their index. Comment 0 Comment 1 Comment 2 Comment 3 .....
How do I achieve this using custom functions ? Thanks
If you have control over the context (and you probably do), you can implement this with property accessors. Let's say your context contains the comments in jumbled order:
var context = {
comments: [
{ idx:6, text:'violet' },
{ idx:1, text:'orange' },
{ idx:0, text:'red' },
{ idx:5, text:'indigo' },
{ idx:3, text:'green' },
{ idx:2, text:'yellow' },
{ idx:4, text:'blue' },
],
};
You could just sort the comments array in place before rendering your template (note that for numeric values, you can just subtract them to get natural ordering):
context.comments.sort( function(a,b) { return a.idx - b.idx; } );
The problem with that is that will modify the context object, which you may not want to do. A solution is to provide a custom accessor that will return the comments sorted by some custom property. Here's how we can do that:
Object.defineProperty( context, 'commentsByIdx', {
get: function() {
// note that we call concat() to create a copy of
// the array; otherwise we are modifying the
// the original array, which is a side effect
return this.comments.concat()
.sort( function(a,b) { return a.idx - b.idx } );
}
});
You can see this solution in action here: http://jsfiddle.net/Jammerwoch/ShZLY/
The other approach is to implement a Handlebars block helper. This approach will work better if you don't have much control over the context (or don't want to contaminate it with custom properties). Simply register a Handlebars helper:
Handlebars.registerHelper('eachByIdx', function(context,options){
var output = '';
var contextSorted = context.concat()
.sort( function(a,b) { return a.idx - b.idx } );
for(var i=0, j=contextSorted.length; i<j; i++) {
output += options.fn(contextSorted[i]);
}
return output;
});
And call it like so in your template:
{{#eachByIdx comments}}
<li>{{text}}</li>
{{/eachByIdx}}
See it in action here: http://jsfiddle.net/Jammerwoch/aeCYg/1/
All in all, I find the first method preferable, as it creates a new view of your data that's potentially useful outside of Handlebars. Furthermore, to the casual reader of Handlebars code, it will make more sense.
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