Foreach knockout with list of functions
I am having trouble binding foreach to a list of functions. I want the inner context to be the function itself, but instead the context is associated with the result of the function call. Here's a simple example to illustrate this: ( JSFiddle )
JS:
ko.applyBindings({
list: [
function() {
return "hodor";
}
]
});
HTML:
<!-- ko foreach: list -->
<span data-bind="text: typeof $data"></span>
<span data-bind="text: $data"></span>
<br />
<!-- /ko -->
Output: "string foo", but I would like it to be "function function () {return" foo ";}"
As a workaround, I can do it $parent.list[$index()]
, but this is really ugly and I would like to avoid this syntax if possible.
(For the sake of explanation in my real use these are not simple functions, but functions to which I have attached additional properties that I want to refer to, but I cannot refer to them because the knockout calls them)
EDIT:
There seems to be a KO version here. Until 3.0, this was not a problem, the context was always attached to a function not to a value. In version 3.0, using $rawData
, you get a function, not this value, but on 3.2, this is not what I am trying to use.
I updated the above fiddle to use 3.2 and here's a fiddle for every version including $rawData
(except 2.3 where $ rawData doesn't exist)
Knockout 2.3 Violin : $rawData
Not Required
Knockout 3.0 violin : $rawData
works
Knockout 3.2 Violin : $rawData
Doesn't Work.
Could this be a KO 3.2 bug?
source to share
No, that was a bug in KO 3.0.
In <2.3 this was a missing feature. Because without, $rawData
you could not work with arrays containing obsablez [ko.observable(1), ko.observable(2)]
.
It $rawData
was introduced in 3.0 , but it was a bug. This was fixed in 3.1 https://github.com/knockout/knockout/pull/1206 .
So this is the correct behavior presented by daedalus28 in the above linked issue:
$rawData
must be a return value if it is a function but not an observable. If it is an observable (or the result of a function is an observable) it should be unwrapped by$data
, not$rawData
-$rawData
should store the actual observable (the result of a function)
Your use case is currently not supported by KO.
So, you should use on, $parent.list[$index()]
or not directly put your functions into an array.
Wrap them up to the observable
list: [
ko.observable(function() {
return "foo";
}),
ko.observable(function() {
return "bar";
}),
ko.observable(function() {
return "hodor";
})
]
Demo JSFiddle .
or put them on some mock objects:
list: [
{bar: function() {
return "foo";
}},
{bar: function() {
return "bar";
}},
{bar: function() {
return "hodor";
}}
]
And you write:
<span data-bind="text: bar"></span>
Demo JSFiddle .
source to share