Handlebars.js пользовательская функция сортировки

Я использую Handlebars для отображения комментариев.

{{#each COMMENTS}}
     <div class="heightfix">
          <div class="commentIcon"></div>&nbsp;&nbsp;
             <label id="commentDate1" class="bold">{{COMMENTON}}</label>:&nbsp;
             <label id="commentCreator1" class="bold">{{COMMENTBY_FIRSTNAME}} {{COMMENTBY_LASTNAME}}</label>&nbsp;&nbsp;
             <label class="commentContent" id="commenttext_{{ID}}">{{COMMENTTEXT}}</label>
     </div>                                  
{{/each}}   

В этих комментариях у меня есть ИНДЕКС. Я хотел бы отображать комментарии в соответствии с их индексом. Комментарий 0 Комментарий 1 Комментарий 2 Комментарий 3 .....

Как мне добиться этого с помощью пользовательских функций? Спасибо

2 ответа

Решение

Метод 1: Пользовательский Accessor

Если у вас есть контроль над контекстом (и вы, вероятно, делаете), вы можете реализовать это с помощью методов доступа к свойствам. Допустим, ваш контекст содержит комментарии в беспорядочном порядке:

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' },
    ],
};

Вы могли бы просто отсортировать comments массив перед размещением шаблона (обратите внимание, что для числовых значений вы можете просто вычесть их, чтобы получить естественное упорядочение):

context.comments.sort( function(a,b) { return a.idx - b.idx; } );

Проблема в том, что изменит объект контекста, чего вы, возможно, не захотите делать. Решение состоит в том, чтобы предоставить пользовательский метод доступа, который будет возвращать комментарии, отсортированные по некоторому пользовательскому свойству. Вот как мы можем это сделать:

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 } );
    }
});

Вы можете увидеть это решение в действии здесь: http://jsfiddle.net/Jammerwoch/ShZLY/

Способ 2: Помощник блока руля

Другой подход заключается в реализации вспомогательного блока Handlebars. Этот подход будет работать лучше, если у вас нет большого контроля над контекстом (или вы не хотите загрязнять его пользовательскими свойствами). Просто зарегистрируйте помощника Handlebars:

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;
});

И назовите это так в вашем шаблоне:

{{#eachByIdx comments}}
    <li>{{text}}</li>
{{/eachByIdx}}

Смотрите это в действии здесь: http://jsfiddle.net/Jammerwoch/aeCYg/1/

В целом, я считаю, что первый метод предпочтительнее, так как он создает новое представление о ваших данных, которое потенциально полезно вне Handlebars. Кроме того, для обычного читателя кода Handlebars это будет иметь больше смысла.

Ниже я сортирую элементы для галереи изображений

Надо знать

  • Функция занимает 3 периметра
    • данные для сортировки
    • значение для сортировки
    • заголовок отсортированных данных
  • Функция возвращает HTML с отсортированными данными

Данные

{
"imageUrl" : "img/shoes.jpg",
"category" : "shoes"
},
{
"imageUrl" : "img/hat.jpg",
"category" : "hat"
}

Функция сортировки узла JS на стороне сервера

"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 
};

Разметка руля на стороне клиента

 {{#sort data 'shoes' 'Jordans'}}{{/sort}}
  • вызовите помощника и добавьте 3 параметра
    • 1-й параметр включает в себя все данные для сортировки data
    • 2-й параметр - это значение для сортировки 'shoes'
    • 3-й параметр - заголовок отсортированных данных 'Jordans'
Другие вопросы по тегам