把手Block Helper:每个都有排序

时间:2021-04-09 14:29:08

I have an array of json objects which I output using a Handlebars template; I am currently doing using {{#each object}}...{{/each}}. I now need to sort the objects by one of the object's properties, which again is no problem using a handlebars helper & coffeescript, however, I have a problem in my template in that I cannot work out how to iterate over the sorted array using each.

我有一个json对象数组,我使用Handlebars模板输出;我目前正在使用{{#each object}} ... {{/ each}}。我现在需要通过对象的一个​​属性对对象进行排序,使用把手助手和coffeescript再次没有问题,但是,我的模板中有一个问题,我无法解决如何使用每个对象进行迭代。

My research so far indicates that I probably need to write a custom Handlebars helper which will, in effect, be:

到目前为止,我的研究表明,我可能需要编写一个自定义Handlebars帮助器,实际上,它将是:

{{#each_with_sort array}}

My existing sort helper is like this

我现有的排序助手是这样的

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

but, I am struggling to be able to use the sorted array in the template - for example, it is not as simple as

但是,我很难在模板中使用排序数组 - 例如,它不是那么简单

 {{#each sort_me(myArray)}}

The data is coming from a third party API, so I have to perform sorting in handlebars/coffeescript.

数据来自第三方API,因此我必须在handlebars / coffeescript中执行排序。

1 个解决方案

#1


10  

The easiest thing to do would be to sort the data before it gets to Handlebars, then you can use {{#each ...}} as usual and no helpers are needed. This sort of approach is quite common with Handlebars, the template is often split into two pieces: a (Java|Coffee)Script piece for data mangling/rearrangement and the template proper.

最简单的方法是在数据到达Handlebars之前对数据进行排序,然后像往常一样使用{{#each ...}}并且不需要帮助程序。这种方法在Handlebars中很常见,模板通常分为两部分:一个(Java | Coffee)脚本部分用于数据修改/重新排列和模板本身。

As an aside, you'll want to adjust your comparator function to behave property. From the fine manual:

另外,您需要调整比较器函数以表现属性。从精细手册:

If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:

如果提供compareFunction,则根据compare函数的返回值对数组元素进行排序。如果a和b是被比较的两个元素,那么:

  • If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
  • 如果compareFunction(a,b)小于0,则将a排序为低于b的索引,即a先到。

  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
  • 如果compareFunction(a,b)返回0,则保持a和b相对于彼此保持不变,但是对于所有不同的元素进行排序。注意:ECMAscript标准不保证这种行为,因此并非所有浏览器(例如可追溯到至少2003年的Mozilla版本)都尊重这一点。

  • If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
  • 如果compareFunction(a,b)大于0,则将b排序为低于a的索引。

So you want to return 0 if a.sort_index and b.sort_index are the same, something more like this:

所以如果a.sort_index和b.sort_index是相同的,你想返回0,更像是这样:

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

If you must do the sorting inside the template then you'd need to add a custom each_with_sort helper to do both the sorting and the iteration, something like this:

如果你必须在模板中进行排序,那么你需要添加一个自定义的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
)

and your template would be like this:

你的模板是这样的:

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

Demo: http://jsfiddle.net/ambiguous/zusq2tt4/

#1


10  

The easiest thing to do would be to sort the data before it gets to Handlebars, then you can use {{#each ...}} as usual and no helpers are needed. This sort of approach is quite common with Handlebars, the template is often split into two pieces: a (Java|Coffee)Script piece for data mangling/rearrangement and the template proper.

最简单的方法是在数据到达Handlebars之前对数据进行排序,然后像往常一样使用{{#each ...}}并且不需要帮助程序。这种方法在Handlebars中很常见,模板通常分为两部分:一个(Java | Coffee)脚本部分用于数据修改/重新排列和模板本身。

As an aside, you'll want to adjust your comparator function to behave property. From the fine manual:

另外,您需要调整比较器函数以表现属性。从精细手册:

If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:

如果提供compareFunction,则根据compare函数的返回值对数组元素进行排序。如果a和b是被比较的两个元素,那么:

  • If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
  • 如果compareFunction(a,b)小于0,则将a排序为低于b的索引,即a先到。

  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
  • 如果compareFunction(a,b)返回0,则保持a和b相对于彼此保持不变,但是对于所有不同的元素进行排序。注意:ECMAscript标准不保证这种行为,因此并非所有浏览器(例如可追溯到至少2003年的Mozilla版本)都尊重这一点。

  • If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
  • 如果compareFunction(a,b)大于0,则将b排序为低于a的索引。

So you want to return 0 if a.sort_index and b.sort_index are the same, something more like this:

所以如果a.sort_index和b.sort_index是相同的,你想返回0,更像是这样:

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

If you must do the sorting inside the template then you'd need to add a custom each_with_sort helper to do both the sorting and the iteration, something like this:

如果你必须在模板中进行排序,那么你需要添加一个自定义的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
)

and your template would be like this:

你的模板是这样的:

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

Demo: http://jsfiddle.net/ambiguous/zusq2tt4/