Подтвердить что ты не робот

В Усы, Как получить индекс текущего раздела

Я использую Mustache и используя данные

{ "names": [ {"name":"John"}, {"name":"Mary"} ] }

Мой шаблон усы:

{{#names}}
    {{name}}
{{/names}}

То, что я хочу сделать, - это получить индекс текущего числа в массиве. Что-то вроде:

{{#names}}
    {{name}} is {{index}}
{{/names}}

и распечатать его

John is 1
Mary is 2

Можно ли получить это с Усы? или с ручками или другим расширением?

4b9b3361

Ответ 1

Для справки, эта функциональность теперь встроена в Handlebars, которая имеет совместимость с Mustache.

Используйте {{@index}}

{{#names}}
    {{name}} is {{@index}}
{{/names}}

Джон = 0

Мэри 1

Ответ 2

Вот как я это делаю в JavaScript:

var idx = 0;

var data = { 
   "names": [ 
       {"name":"John"}, 
       {"name":"Mary"} 
    ],
    "idx": function() {
        return idx++;
    }
};

var html = Mustache.render(template, data);

Ваш шаблон:

{{#names}}
    {{name}} is {{idx}}
{{/names}}

Ответ 3

В handlebars.js вы можете выполнить это с помощью вспомогательной функции. (На самом деле одно из преимуществ, упомянутых здесь о рулях здесь http://yehudakatz.com/2010/09/09/announcing-handlebars-js/, заключается в том, что вы можете использовать помощники вместо того, чтобы переписывать объекты перед вызовом шаблона.

Итак, вы можете сделать это:

  var nameIndex = 0;
  Handlebars.registerHelper('name_with_index', function() {
    nameIndex++;
    return this.name + " is " + nameIndex;
  })

И тогда ваш шаблон может быть следующим:

{{#names}}
<li>{{name_with_index}}</li>
{{/names}}

Ваши данные те же, что и раньше, т.е.:

{ "names": [ {"name":"John"}, {"name":"Mary"} ] };

И вы получите этот вывод:

<li>John is 1</li>
<li>Mary is 2</li>

Чтобы это действительно работало, nameIndex должен получать reset каждый раз при визуализации шаблона, поэтому для этого вы можете иметь помощник reset в начале списка. Таким образом, полный код выглядит следующим образом:

  var data = { "names": [ {"name":"John"}, {"name":"Mary"} ] };
  var templateSource = "<ul>{{reset_index}}{{#names}}<li>{{name_with_index}}</li>{{/names}}</ul>";
  var template = Handlebars.compile(templateSource);

  var helpers = function() {
    var nameIndex = 0;
    Handlebars.registerHelper('name_with_index', function() {
      nameIndex++;
      return this.name + " is " + nameIndex;
    });
    Handlebars.registerHelper('reset_index', function() {
      nameIndex = 0;
    })
  }();

  var htmlResult= template(data);
  $('#target').html(htmlResult);

  var htmlResult2= template(data);
  $('#target2').html(htmlResult2);

(Это может корректно отобразить шаблон дважды.)

Ответ 4

Вы можете запустить следующий цикл в списке объектов.

Это решение имеет следующие преимущества:

  • Не изменяет данные модели
  • Доступ к индексу можно получить несколько раз

Код:

for( var i=0; i< the_list.length; i++) {
    the_list[i].idx = (function(in_i){return in_i+1;})(i);
}

Объяснение:

Вместо имени переменной используется функция, поэтому данные не мутируются. Закрытие используется для возврата значения "i" во время создания функции в цикле вместо значения я в конце цикла.

Ответ 5

Великий помощник здесь:

// {{#each_with_index records}}
//  <li class="legend_item{{index}}"><span></span>{{Name}}</li>
// {{/each_with_index}}

Handlebars.registerHelper("each_with_index", function(array, fn) {
    var buffer = "";
    for (var i = 0, j = array.length; i < j; i++) {
        var item = array[i];

        // stick an index property onto the item, starting with 1, may make configurable later
        item.index = i+1;

        // show the inside of the block
        buffer += fn(item);
    }

    // return the finished buffer
    return buffer;

});

Источник: https://gist.github.com/1048968

Ответ 6

Лучшим подходом для Mustache будет использование функции, которая получает индекс, используя indexOf:

var data = { 
   names: [ {"name":"John"}, {"name":"Mary"} ],
    index: function() {
        return data.names.indexOf(this);
    }
};

var html = Mustache.render(template, data);

В вашем шаблоне:

{{#names}}
    {{name}} is {{index}}
{{/names}}

Недостатком является то, что эта функция index имеет массив жесткого кодирования data.names, чтобы сделать его более динамичным, мы можем использовать другую функцию, подобную этой:

var data = { 
   names: [ {"name":"John"}, {"name":"Mary"} ],
    index: function() {
        return function(array, render) {
            return data[array].indexOf(this);
        }
    }
};

var html = Mustache.render(template, data);

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

{{#names}}
    {{name}} is {{#index}}names{{/index}}
{{/names}}

Также небольшой недостаток заключается в том, что вы должны передать имя массива функции индекса в этом примере names, {{#index}}names{{/index}}.

Ответ 7

Если вы можете управлять выходом строки JSON, попробуйте это.

{ "names": [ {"name":"John", "index":"1"}, {"name":"Mary", "index":"2"} ] }

Поэтому, когда вы создаете строку JSON, добавьте индекс как другое свойство для каждого объекта.

Ответ 8

Моим основным прецедентом для этого была возможность размещения "активного" класса на элементах. Я объединился с объединением помощника "equals" с помощником "index_for_each", но это было слишком сложно.

Вместо этого я придумал следующий базовый "активный" помощник. Это очень специфично, но является таким распространенным вариантом использования для любого сценария меню/выбора:

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

  <ul>
    {{{active 2}}}
    {{#each menuItem}}
      <li class="{{{active}}}">{{this}}</li>
    {{/each}}
  </div>

Сделал бы 3-й пункт меню "class=" активным ".

Помощник здесь (это версия CoffeeScript):

active = 0
cur = 0
handlebars.registerHelper 'active', (item, context) ->
  if arguments.length == 2
    active = item
    cur = 0
    ''
  else if cur++ == active
    'active'

Ответ 9

Пока вы не путешествуете в несколько массивов, вы можете хранить индекс в помощнике и просто увеличивать его при изменении контекста. Я использую что-то похожее на следующее:

var data = {
    foo: [{a: 'a', 'b': 'a'}, {'a':'b', 'b':'b'}], 
    i: function indexer() {
        indexer.i = indexer.i || 0;
        if (indexer.last !== this && indexer.last) {                                          
            indexer.i++;
        }   
        indexer.last = this;
        return String(indexer.i);
     }   
};

Mustache.render('{{#foo}}{{a}}{{i}}{{b}}{{i}}{{/foo}}', data);

Ответ 10

(Протестировано в node 4.4.7, усы 2.2.1.)

Если вам нужен хороший чистый функциональный способ, который не включает глобальные переменные или мутирует сами объекты, используйте эту функцию;

var withIds = function(list, propertyName, firstIndex) {
    firstIndex |= 0;
    return list.map( (item, idx) => {
        var augmented = Object.create(item);
        augmented[propertyName] = idx + firstIndex;
        return augmented;
    })
};

Используйте его, когда вы собираете свое представление;

var view = {
    peopleWithIds: withIds(people, 'id', 1) // add 'id' property to all people, starting at index 1
};

Оптимальный подход к этому подходу состоит в том, что он создает новый набор объектов "viewmodel", используя старый набор в качестве прототипов. Вы можете прочитать person.id так же, как вы читали бы person.firstName. Однако эта функция не изменяет ваши объекты людей вообще, поэтому другой код (который, возможно, полагался на свойство ID, не находясь там), не будет затронут.

Алгоритм O (N), такой приятный и быстрый.