KO 1.3, foreach and index of current row

4,167 views
Skip to first unread message

Johan Nordberg

unread,
Oct 20, 2011, 3:03:33 PM10/20/11
to knock...@googlegroups.com
I need the index of the current row in a foreach binding. Is this possible in 1.3?

<div data-bind="foreach: items">
   <span data-bind="text: $index"></span>
</div>


rpn

unread,
Oct 20, 2011, 3:20:17 PM10/20/11
to knock...@googlegroups.com
The index is not a concept that is known in the foreach binding.

My suggestion is to attach an index to your items like:

//attach index to items whenever array changes
viewModel.items.subscribe(function({
    var items this.items();
    for (var 0items.lengthji++{
       var item item[i];
        if (!item.index{
           item.index ko.observable(i);  
        else {
           item.index(i);   
        }
    }
}viewModel);

 Now, whever the structure of your array changes, the index observable on each item will be updated.

Johan Nordberg

unread,
Oct 20, 2011, 4:39:48 PM10/20/11
to knock...@googlegroups.com
Thanks for your reply. Too bad there isn't an $index in the same way as $parent. The models gets so messy when you need such code in them.

Can I do an 1.2 style template binding and get the index? 

gaffe

unread,
Oct 20, 2011, 6:34:42 PM10/20/11
to KnockoutJS
I am also converting a few old jquery {{each (i, item) things }} into
the new 1.3 foreach because I want to stop using jquery templates
altogether, so this is helpful, thanks.

However, I have a binding that looks like:

data-bind="value: evals.CompletionDate, jqueryui:
{widget:'datepicker', options: {dateFormat: 'm/d/
yy',changeMonth:true,changeYear:true,onClose:function()
{ viewModel.selectedEval(i);viewModel.Projects()
[viewModel.selectedProjectIndex()].Evaluations()
[viewModel.selectedEval()].CompletionDate(this.value);
saveEval(); } }, event: {focus: function()
{ viewModel.selectedEval(i); } } }"

and in the onClose function of my datepicker the "this" object is the
date that was picked, not the current item, so is there a way to set
certain values within this scope of the new foreach like the
templateOptions binding does?

Thanks!

Johan Nordberg

unread,
Oct 21, 2011, 1:24:48 AM10/21/11
to knock...@googlegroups.com
Maybe a observableArrayWithIndex would be kind of cool. Then you could make it reusable and keep this code out of the view model.

I know you've done a bunch of overloads on observables, but I never done one myself. 

Tom Thorp

unread,
Oct 21, 2011, 11:51:05 AM10/21/11
to knock...@googlegroups.com
Can I ask, what do you need the index for?

Scott Duncombe

unread,
Oct 21, 2011, 12:32:58 PM10/21/11
to knock...@googlegroups.com
I was able to use the $parent.indexOf($data) to get the number.

Well ACTUALLY what I had to do was use $root.observableArray().indexOf($data), but I think this was because I was using foreach on an array that was an element of an object. Or something.

Anyway, here's the example: http://jsfiddle.net/mojowen/sVnxQ/

The template that uses the indexOf is towards the bottom that I'm using the create a key.

Johan Nordberg

unread,
Oct 21, 2011, 12:59:22 PM10/21/11
to knock...@googlegroups.com
I use it to create names for form field so that the mvc modelbinder kan create and populate a dictionary. I need to formfields to be named items[0].key and items[0].value, items[1].key, items[1].value, etc.

In this particular case I also posts files, so I cant just post a json object. I need to do a actual form post.

gaffe

unread,
Oct 21, 2011, 3:11:52 PM10/21/11
to KnockoutJS
The index is extremely useful in many cases, such as when it
represents the order in which the items are displayed and that needs
to be manipulated.

Also, in my case I have some legacy javascript functions that perform
a certain operation on a particular item and take the index passed in
as a parameter. I don't want to rewriting a lot of code and
unnecessarily risk introducing bugs, nor do I want to do lookups to
find the index each call, which is slow and inefficient.

Why would anyone want to limit there options and not have access to
the index of an array? I never understood like keep acting as though
it's not needed... not having access to the index breaks the way
arrays are intended to work (directly selecting an element without
having to search for it). Why would you rather than have a bunch of
variables with pointers to those items separately? Or have to search
through it the entire list every time you want to find a single item?

If I want the next or a previous item in my array because I am doing a
calculation, and I don't have the index, I need to create a next and
previous variable that points to those values and search through them
all to populate these first. Perhaps I am missing something, but to
me,
array[index+1] and array[index-1] just seems straightforward and clear
to me.

gaffe

unread,
Oct 21, 2011, 3:16:21 PM10/21/11
to KnockoutJS
Does anyone know the syntax for subscribing to items that are nested
more than one level deep in the viewModel?

I mean, the below works fine if the items are in
viewModel.items

but how do you write that first line if it is:
viewModel.somethings[indexOfThings].items

?

On Oct 20, 3:20 pm, rpn <rnieme...@gmail.com> wrote:

Mark Hahn

unread,
Oct 21, 2011, 4:25:26 PM10/21/11
to knock...@googlegroups.com
The index is extremely useful in many cases,

I include my index in $data.  It is needed for mapping purposes anyway.

Mark Bradley

unread,
Oct 21, 2011, 11:51:58 PM10/21/11
to knock...@googlegroups.com
unless it is an index of filtered results.

e.g. odd/even row highlighting that doesn't act funny for a filtered list

https://github.com/SteveSanderson/knockout/pull/182

On Sat, Oct 22, 2011 at 7:25 AM, Mark Hahn <ma...@boutiquing.com> wrote:
>> The index is extremely useful in many cases,
> I include my index in $data.  It is needed for mapping purposes anyway.
>
>

--
-barkmadley
sent from an internet enabled device
http://barkmadley.com

msudhaka...@gmail.com

unread,
Sep 4, 2012, 3:57:31 AM9/4/12
to knock...@googlegroups.com
<div data-bind="foreach: items">
   <span data-bind="text: $index"></span>
</div>



I need $index value  with +1 ,
means that it is now started with 0, But i need to add +1 for $index so I get the order as 1,2,3 ........... 
Now i am getting 0,1,2,3 ................


What i have to do?? 

rpn

unread,
Sep 5, 2012, 9:18:20 AM9/5/12
to knock...@googlegroups.com, msudhaka...@gmail.com
You can do $index() + 1.  $index is an observable, so you need to call it as a function to get its value in an expression.
Reply all
Reply to author
Forward
0 new messages