2013-07-15 4 views
3

У меня есть массив объектов json, которые выводятся с использованием шаблона Handlebars; В настоящее время я использую {{#each object}} ... {{/ each}}. Теперь мне нужно отсортировать объекты по одному из свойств объекта, что опять же не проблема с помощью помощника handlebars & coffeescript, однако у меня есть проблема в моем шаблоне, так как я не могу решить, как выполнять итерацию по отсортированному массиву, используя каждый ,Handlebars Block Helper: каждый с сортировкой

Мои исследования до сих пор указывает на то, что я, вероятно, нужно написать специальный Рули помощника, который, по сути, быть:

{{#each_with_sort array}} 

Мой существующий помощник сортировки, как этот

Handlebars.registerHelper sort_me => 
    myArray.sort (a,b)-> 
     return if +a.sort_index >= +b.sort_index then 1 else -1 

но, Я изо всех сил стараюсь использовать отсортированный массив в шаблоне - например, это не так просто, как

{{#each sort_me(myArray)}} 

Данные поступают от стороннего API, поэтому мне приходится выполнять сортировку в handlebars/coffeescript.

ответ

8

Проще всего сделать, чтобы отсортировать данные до того, как они попадут в Handlebars, тогда вы можете использовать {{#each ...}}, как обычно, и никакие помощники не нужны. Такой подход довольно часто встречается с Handlebars, шаблон часто разделяется на две части: кусок скрипта (Java | Coffee) для обработки/перестановки данных и собственно шаблона.

Как в стороне, вам нужно настроить функцию компаратора на поведение свойства. От fine manual:

Если compareFunction поставляется, элементы массива сортируются в соответствии со значением возврата функции сравнения. Если a и b два элемента сравнивают, то:

  • Если compareFunction(a, b) меньше 0, сортировать по a с более низким индексом, чем b, т.е. приходит первым.
  • Если compareFunction(a, b) возвращает 0, оставьте a и b без изменений по отношению друг к другу, но отсортированы по всем различным элементам. Примечание. Стандарт ECMAscript не гарантирует такого поведения, и, таким образом, не все браузеры (например, версии Mozilla, датированные как минимум 2003 годом).
  • Если compareFunction(a, b) больше 0, сортировать b по нижнему индексу, чем a.

Итак, вы хотите, чтобы вернуть 0 если a.sort_index и b.sort_index то же самое, что-то больше, как это:

myArray.sort (a,b)-> 
    a = +a.sort_index 
    b = +b.sort_index 
    return 1 if a > b 
    return 0 if a == b 
    return -1 if a < b 

Если вы должны сделать сортировку внутри шаблона, то вам нужно добавить помощник обычай each_with_sort делать как сортировку и итерацию, что-то вроде этого:

# If you're always sorting by sort_index then you don't need the key argument 
# and you might want to put the '+'-casting back in. 
Handlebars.registerHelper('each_with_sort', (array, key, opts) -> 
    data = Handlebars.createFrame(opts.data) if(opts.data) 
    array = array.sort (a, b) -> 
     a = a[key] 
     b = b[key] 
     return 1 if a > b 
     return 0 if a == b 
     return -1 if a < b 
    s = '' 
    for e, i in array 
     data.index = i if(data) # Support the usual @index. 
     s += opts.fn(e, data: data) 
    s 
) 

и ваш шаблон будет выглядеть так:

{{#each_with_sort array "sort_index"}} 
    ... 
{{/each_with_sort}} 

Демо: http://jsfiddle.net/ambiguous/zusq2tt4/

+0

Это отличный ответ! – marty

+0

Как бы выглядел код для помощника, который перебирает свойства объекта отсортированным образом? –

+0

@JoachimBreitner Объекты JavaScript не имеют определенного порядка, поэтому вам нужно будет преобразовать объект в '[[key, value], ...]' array-of-arrays и отсортировать его; или вы можете извлечь ключи в массив, отсортировать массив ключей и выполнить итерацию по отсортированным клавишам. –

Смежные вопросы