Как я могу получить индекс массива в шаблоне Meteor в каждом цикле?

Скажем, у меня есть объект, someObject:

{
  foo: "apple",
  myArray: ["abc", "def"]
}

И помощник шаблона, который выглядит так (и отлично работает):

getArray: function(){
  var self = this;
  self.myArray = self.myArray || [];    
  return self.myArray;
}

Как мне построить html, чтобы получить индекс массива?

Я пробовал:

<template name="someObject"> // takes someObject as data
  {{#each getArray}}
    <div class="item" data-value="{{WHAT GOES HERE?}}">{{this}}</div>
  {{/each}}
</template>

В этом случае this успешно возвращает "abc" и "def". И это хорошо. Но как я могу получить индекс массива, чтобы поместить его в атрибут data-value?

Я пробовал this.index напрямую, но он не определен. Я также пытался использовать помощника:

<template name="someObject"> // takes someObject as data
  {{#each getArray}}
    <div class="item" data-value="{{getindex}}">{{this}}</div>
  {{/each}}
</template>

но в этом помощнике getIndex, когда я выхожу из console.log this, я вижу:

String {0: "a", 1: "b", 2: "c", length: 3}
String {0: "d", 1: "e", 2: "f", length: 3}

Можно ли получить индекс?


person Oliver Lloyd    schedule 14.06.2014    source источник


Ответы (6)


метеор >= 1,2

Пробелы получили много функций в 1.2, в том числе собственный @index. Помощники больше не нужны для решения этой задачи — можно просто сделать это:

{{#each getArray}}
  <div class="item" data-value="{{@index}}">{{this}}</div>
{{/each}}

или, если вы хотите использовать индекс внутри помощника:

{{#each getArray}}
  <div class="item" data-value="{{someHelper @index}}">{{this}}</div>
{{/each}}

метеор ‹ 1,2

Когда-нибудь в будущем пробелы могут дать возможность определять индекс прямо в шаблоне. Однако на момент написания этой статьи единственный способ получить индекс — изменить результат, возвращаемый помощником. Например, getArray может возвращать массив объектов, содержащих value и index, например:

getArray: function() {
  var self = this;
  self.myArray = self.myArray || [];
  return _.map(self.myArray, function(value, index){
    return {value: value, index: index};
  });
}

И шаблон может использовать такой индекс:

<template name="someObject">
  {{#each getArray}}
    <div class="item" data-value="{{index}}">{{value}}</div>
  {{/each}}
</template>

Также см. этот ответ для аналогичного примера с курсорами.

Стоит отметить, что вам, вероятно, не нужно хранить индекс в самой DOM через data-value, если только он не нужен внешнему плагину. Как вы можете видеть в примере ниже, каждый item имеет контекст со значением индекса. Для получения дополнительной информации см. эту запись в блоге. .

Template.someObject.events({
  'click .item': function() {
    console.log(this.index);
  }
});
person David Weldon    schedule 15.06.2014
comment
Спасибо, что прояснили это. Примечание. атрибут данных требуется для чего-то, что я не могу (или не хочу) редактировать, поэтому у меня нет выбора. - person Oliver Lloyd; 15.06.2014
comment
Пробовал это на Meteor 1.2.0.2, и @index по-прежнему возвращает значение undefined. - person earthling; 25.10.2015
comment
Как бы вы отобразили @index + 1? Например. начинать с 1, а не с нуля? - person Barry Michael Doyle; 03.02.2016
comment
Вам понадобится помощник. В приведенном выше примере someHelper можно реализовать так, чтобы он возвращал значение своего аргумента + 1. - person David Weldon; 03.02.2016

Вы также можете сделать это многоразовым помощником. Удобно иметь:

JS:

UI.registerHelper('addIndex', function (all) {
    return _.map(all, function(val, index) {
        return {index: index, value: val};
    });
});

HTML:

{{#each addIndex somearray}}
<div>
   {{index}}: {{value}}
</div>
{{/each}}
person Christian Fritz    schedule 15.06.2014

Это изменение готовится, и вы сможете сделать {{@index}}. Когда метеор поддерживает самую последнюю версию руля.

person pcatre    schedule 04.05.2015
comment
В то время, когда я писал это, он еще не был выпущен. Наверное, так и есть :/ - person pcatre; 29.06.2015
comment
Это был релиз как часть Meteor 1.2. - person kynan; 26.02.2017

Вы можете изменить getArray так, чтобы он возвращал массив кортежей и сохранял там индекс.

person Erez Hochman    schedule 14.06.2014

Вот пример того, как вы можете просто добавить индекс к объекту, и пока у вас не было ключа с именем index, прежде чем он не должен ничему мешать, этот способ работает только с массивами объектов. Теперь, если у вас есть массив значений, вы должны использовать ответ Кристана Фрица.

UI.registerHelper("withIndex", function(obj) {
  obj = obj || [];
  _.each(obj, function (object, index) {
    obj[index].index = index;
  });
  return obj;
});

{#each withIndex fields}}
   <div class="form-group field" data-index="{{index}}">
      <label for="{{name}}">{{title}}</label> 
    </div>
{{/each}}
person Patrick Mencias-lewis    schedule 28.07.2015

Вы также можете сделать это с подчеркиванием, предполагая, что вы подписали свой шаблон на массив объектов.

Template.yourTemplate.helpers({
  objectsWithIndex: function() {
    _.map(this.objects, function(value, key) {
      return _.extend(value, {
        index: key
      });
    });
    return this.objects;
  }
});

и в вашем html...

<template name="someObject">
  {{#each objectsWithIndex}}
    <div class="item" data-value="{{index}}">{{value}}</div>
  {{/each}}
</template>
person jasenkoh    schedule 24.08.2015