Рули / Усы - Есть ли встроенный способ перебирать свойства объекта? - PullRequest
201 голосов
/ 30 января 2012

Как видно из названия вопроса, есть ли усы / руль способ циклически проходить через объект свойства?

Так что с

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
}

Могу ли я тогдасделать что-то в шаблонизаторе , что будет эквивалентно

for(var prop in o)
{
    // with say, prop a variable in the template and value the property value
}

?

Ответы [ 8 ]

422 голосов
/ 08 июля 2013

Встроенная поддержка начиная с Handlebars 1.0rc1

Поддержка этой функциональности была добавлена ​​ в Handlebars.js, поэтому больше нет необходимости во внешних помощниках.

Как его использовать

Для массивов:

{{#each myArray}}
    Index: {{@index}} Value = {{this}}
{{/each}}

Для объектов:

{{#each myObject}}
    Key: {{@key}} Value = {{this}}
{{/each}}

Обратите внимание, что только свойства, передающие hasOwnPropertyТест будет перечислен.

69 голосов
/ 30 января 2012

Это довольно легко реализовать в качестве помощника:

Handlebars.registerHelper('eachProperty', function(context, options) {
    var ret = "";
    for(var prop in context)
    {
        ret = ret + options.fn({property:prop,value:context[prop]});
    }
    return ret;
});

Затем, используя его так:

{{#eachProperty object}}
    {{property}}: {{value}}<br/>
{{/eachProperty }}
27 голосов
/ 30 января 2012

РЕДАКТИРОВАТЬ: у Handlebars теперь есть встроенный способ сделать это;см. выбранный ответ выше.При работе с обычными усами все еще действует нижеследующее.

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

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
},
mustacheFormattedData = { 'people' : [] };

for (var prop in o){
  if (o.hasOwnProperty(prop)){
    mustacheFormattedData['people'].push({
      'key' : prop,
      'value' : o[prop]
     });
  }
}

Теперь ваш шаблон усов будет выглядеть примерно так:

{{#people}}
  {{key}} : {{value}}
{{/people}}

ПроверьтеРаздел «Непустые списки» здесь: https://github.com/janl/mustache.js

4 голосов
/ 29 мая 2013

Это ответ @ Ben, обновленный для использования с Ember ... обратите внимание, вы должны использовать Ember.get, потому что контекст передается как String.

Ember.Handlebars.registerHelper('eachProperty', function(context, options) {
  var ret = "";
  var newContext = Ember.get(this, context);
  for(var prop in newContext)
  {
    if (newContext.hasOwnProperty(prop)) {
      ret = ret + options.fn({property:prop,value:newContext[prop]});
    }
  }
  return ret;
});

Шаблон:

{{#eachProperty object}}
  {{key}}: {{value}}<br/>
{{/eachProperty }}
1 голос
/ 03 августа 2012

@ Ответ Амита хорош, потому что он будет работать как на Усе, так и на Руле.

Что касается решений только для Handlebars, я видел несколько, и мне нравится each_with_key block helper в https://gist.github.com/1371586 лучший.

  • Позволяет перебирать литералы объектов без необходимости сначала их реструктурировать, а
  • Он дает вам контроль над тем, что вы называете ключевой переменной. Со многими другими решениями вы должны быть осторожны с использованием объектных ключей с именем 'key' или 'property' и т. Д.
0 голосов
/ 12 ноября 2018

Я использовал старую версию 1.0.beta.6 рулей, я думаю, что где-то во время 1.1 - 1.3 эта функциональность была добавлена, поэтому обновление до 1.3.0 решило проблему, вот использование:

Использование:

{{#each object}}
  Key {{@key}} : Value {{this}}
{{/people}}
0 голосов
/ 07 июля 2014

Это вспомогательная функция для mustacheJS, без предварительного форматирования данных и получения ее во время рендеринга.

var data = {
    valueFromMap: function() {
        return function(text, render) {
            // "this" will be an object with map key property
            // text will be color that we have between the mustache-tags
            // in the template
            // render is the function that mustache gives us

            // still need to loop since we have no idea what the key is
            // but there will only be one
            for ( var key in this) {
                if (this.hasOwnProperty(key)) {
                    return render(this[key][text]);
                }
            }
        };
    },

    list: {
        blueHorse: {
            color: 'blue'
        },

        redHorse: {
            color: 'red'
        }
    }
};

Шаблон:

{{#list}}
    {{#.}}<span>color: {{#valueFromMap}}color{{/valueFromMap}}</span> <br/>{{/.}}
{{/list}}

Выходы:

color: blue
color: red

(порядок может быть случайным - это карта) Это может быть полезно, если вы знаете нужный элемент карты.Просто следите за ложными значениями.

0 голосов
/ 10 апреля 2013

Спасибо за решение Бена, мой вариант использования для отображения только определенных полей в порядке

с объектом

Код:

    handlebars.registerHelper('eachToDisplayProperty', function(context, toDisplays, options) {
    var ret = "";
    var toDisplayKeyList = toDisplays.split(",");
    for(var i = 0; i < toDisplayKeyList.length; i++) {
        toDisplayKey = toDisplayKeyList[i];
        if(context[toDisplayKey]) {
            ret = ret + options.fn({
                property : toDisplayKey,
                value : context[toDisplayKey]
            });
        }

    }
    return ret;
});

Исходный объект:

   { locationDesc:"abc", name:"ghi", description:"def", four:"you wont see this"}

Шаблон:

{{#eachToDisplayProperty this "locationDesc,description,name"}}
    <div>
        {{property}} --- {{value}}
    </div>
    {{/eachToDisplayProperty}}

Выход:

locationDesc --- abc
description --- def
name --- ghi
...