Access index of $parent in knockout.js
Asked Answered
G

2

90

In knockout.js 2.1.0, in a template using the foreach binding, you can access the current item's index though the $index() function. In a nested foreach binding, is there any way to access the index of the $parent from a template?

Say I have a data structure like this:

var application = {
  topModel: [
    {
      {subModel: [{'foo':'foo'}, { 'bar':'bar'}]}, // this has top:0 and sub:0
      {subModel: [{'foo2':'foo2'}, { 'bar2':'bar2'}]} // this has top:0 and sub:1
    },
    {
      {subModel: [{'foo':'foo'}, { 'bar':'bar'}]} // this is top:1 sub:0
    },
    {
      {subModel: [{'foo':'foo'}, { 'bar':'bar'}]} // this is top:2 sub:0
      {subModel: [{'foo':'foo'}, { 'bar':'bar'}]} // this is top:2 sub:1
    },
    ...
    ]};

With this, I want to print the path to each model, using indices: [topModel-index subModel-index], so that the output will be something like:

[0 0]
[0 1]
[1 0]
[2 0]
[2 1]
...

I have bound the models using foreach, but I can't figure out how to access the topModel's index in the context of the subModel. The following example shows an approach I have tried, but it doesn't work, as I can't figure out how to access the index of the $parent referrer.

<!--ko foreach: topModel -->
<!--ko foreach: subModel -->
  [<span data-bind="text: $parent.index()"></span>
  <span data-bind="text: $index()"></span>]
<!--/ko-->
<!--/ko-->

Should print out: 0 1, 0 2, 1 0, 1 1, 1 2, 2 0, 2 1, ...

Gennygeno answered 11/6, 2012 at 10:39 Comment(8)
You don't actually need that () after the $index there.Retool
Also, if you could create a jsfiddle with what you have, that would make it easier. Or post your data source and view model code.Retool
As for now, I'm only working on prototyping, so I don't have much more than the given example. I'm open to suggestions using other approaches, though.Caron
Maybe describe what you are trying to do, rather than how. There may be a different approach.Retool
Thanks. I changed my question, and hopefully it's more clear now?Caron
Possibly. But why do you need the indexes? The may be a totally different way of solving your problem.Retool
My challenge is that I need to apply a class to the submodels based on their parent's position in the list, i.e. all odd indexed topModels' subModels.Caron
let us continue this discussion in chatRetool
M
191

to access the index of the parent object use

$parentContext.$index()

rather than

$parent.index()
Mazza answered 13/6, 2012 at 10:56 Comment(6)
Though, to be overly explicit in the name of brainlessness, you still have to $parentContext.$index() with the parens. ;^) A little more on $parentContext here, fwiw.Estrone
@Estrone not for $index, as per Matthew's comment on the original question "you don't actually need that () after the $index there." $index is a special variable rather than an observable.Mazza
When I used $parentConsent.$index sans () in a template, I get the function underlying it through an implicit toString. Working code snippet (that doesn't eval to the function's string representation): attr: { id: 'field' + $parentContext.$index() + '-' + $index() }"Estrone
thanks - definitely worth noting, in the context of a composite value you would need to add the () however if you were binding an element to the $parentContext.$index as per the question you don't need it.Mazza
Need parentheses $parentContext.$index()Lutyens
Just wanted to add that $parentContext.$parentContext.$index() works as you would expect too.Gaud
B
3

The easiest way you can find out is download "knockout context" for chrome. This shows you what data is bound to what element and also lets you see the available functions/variables to that particular bound element. It's an amazing tool for situations like these.

Beseem answered 16/5, 2016 at 7:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.