Reputation: 2063
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
Upvotes: 2
Views: 7033
Reputation: 29
Below am sorting items for an image gallery
Need to know
Data
{
"imageUrl" : "img/shoes.jpg",
"category" : "shoes"
},
{
"imageUrl" : "img/hat.jpg",
"category" : "hat"
}
JS Node Sort Function server side
"use strict";
var helpers = module.exports;
helpers.sort = function(data, value, heading) {
var str = '<div class="row">'+
'<div class="container headings">'+
'<h2 class="center">'+heading+'</h2>'+ // heading data from Markdown
'<hr>'+
'</div>'+
'<div class="swap"><i class="material-icons">swap_horiz</i></div>'+
'<div class="carousel">';
data.forEach(function(gal){ // loop through all data
if (gal.category === value) { // sort data by value
str += '<a class="carousel-item" href="#!"><img src="'+gal.imageUrl+'" alt="gallery_image"></a>'; // gallery item
}
})
str += '</div>'+
'</div>'+
'</div>';
return str; // return sorted html data
};
Handlebars Markup client side
{{#sort data 'shoes' 'Jordans'}}{{/sort}}
data
'shoes'
'Jordans'
Upvotes: 0
Reputation: 27282
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.
Upvotes: 12