Accessing Index in #each in emberjs
Asked Answered
H

5

50

Please check out the code attached:

http://jsbin.com/atuBaXE/2/

I am trying to access the index using {{@index}} but it seems not to be compiling. I think handlebars supports that:

{{#each item in model}}
  {{@index}} 
  {{item}}
{{/each}}

It is not working for me. I can't figure out if the {{@index}} is supported or not.

I am using:

  • Ember.VERSION : 1.0.0
  • Handlebars.VERSION : 1.0.0
Harvest answered 5/11, 2013 at 17:55 Comment(1)
Tracking in: github.com/toranb/ember-template-compiler/issues/16Deaver
D
139

UPDATE

Since this PR, it's now possible to use the each helper with index, taking advance of the new block params syntax. This is available on canary and hopefully will be enabled by default in ember 1.11

{{#each model as |item index|}}
  <li>
    Index: {{index}} Content: {{item}}
  </li>
{{/each}}

Live sample

FOR OLD VERSIONS

You can use {{_view.contentIndex}}.

{{#each item in model}}
  <li>
    Index: {{_view.contentIndex}} Content: {{item}}
  </li>
{{/each}}

Live sample

Devonadevondra answered 5/11, 2013 at 18:4 Comment(5)
is there a way to get a 1-indexed value? eg. first item should return 1 (not 0) and last item should return n (not n-1) for an array of n itemsThatch
I think the only way to do it, is wrapping the model in a computed property with the index, like this emberjs.jsbin.com/xeboqegu/1/editDevonadevondra
If the items in the each block are updated e.g. by changing their sort order _view.contentIndex is not updated for all items and can result in a incorrect Index values.Cornemuse
does emblem support block syntax? = each model as |item index| isn't working for me.Impossibility
@loostro I created a helper that simply increments the number passed in to get the 1-based index: pastebin.com/jphC3XnhCoaler
D
4

No it doesn't exist in Ember's version of Handlebars, one way is to use an item controller and add a property to it saying whether it's the first or last etc.

App.IndexController = Ember.ArrayController.extend({
  itemController: 'itemer'
});

App.ItemerController = Ember.ObjectController.extend({
  needs:['index'],
  isFirst: function(){
    return this.get('color') === this.get('controllers.index.firstObject.color');
  }.property('controllers.index.firstObject')
});

http://emberjs.jsbin.com/aPewofu/1/edit

Dode answered 5/11, 2013 at 18:10 Comment(3)
I think what you have wrote is really great I am sure anyone will take advantage of it.Harvest
Is there a danger of too tightly coupling the two controllers?Nester
Not danger, but lack of reusability. It all depends on the use case.Dode
C
3

Note, regarding the @index syntax specifically, as of October 2014:

Ember does not support @index (or any of the other @data type properties).

https://github.com/toranb/ember-template-compiler/issues/16#issuecomment-38823756

Chilung answered 5/2, 2015 at 15:35 Comment(0)
C
2

I like the answer from @kingpin2k--The Ember Way is to use a controller to decorate a model, and in this context we want to decorate it by adding an index property to represent its place in the collection.

I do it slightly differently, by building a separate collection of instance controllers decorated for the task at hand:

App.PostsIndexController = Ember.ArrayController.extend({
  indexedContent: function() {
    get('content').map(function(item, index) {
      App.PostsItemController.create({
        content: item,
        index: index
      });
    });
  }.property('content')
});

App.PostsItemController = Ember.ObjectController.extend({
  index: null
});
Chavey answered 16/5, 2014 at 20:29 Comment(0)
C
1

If you're just looking to display the index as a 1-indexed value in your view, you could also give CSS Counters a shot. They are supported all the way back to IE 8.

Conlan answered 17/4, 2015 at 17:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.