I am having trouble getting a Knockout component to work - i can't seem to get it to bind properly to the members of an array on my ViewModel during a foreach
accessed using $index
.
In this Fiddle you will see what I mean.
There are two little view Models:
function OtherThingViewModel(thingString){
this.thingString = ko.observable(thingString);
}
function ThingViewModel(thingNumber, thing){
this.thingNumber = ko.observable(thingNumber);
}
Instances are created in the main viewModel:
function ViewModel(){
var self = this;
this.things = [
new ThingViewModel(1),
new ThingViewModel(2),
new ThingViewModel(3)
];
this.otherThings = [
new OtherThingViewModel("a Thing"),
new OtherThingViewModel("another Thing"),
new OtherThingViewModel("some Thing")
];
this.specialThing = ko.unwrap(this.things)[0];
this.specialOtherThing = ko.unwrap(this.otherThings)[0];
};
Then I have a component:
ko.components.register('combinedthing-component', {
template:
'<div>'
+ ' <h3 data-bind="text: \'Thing \' + thing.thingNumber()"></h3>'
+ ' <p>'
+ ' <label>thingNumber: <input data-bind="value: thing.thingNumber" /></label>'
+ ' <span data-bind="text: thing.thingNumber" />'
+ ' </p>'
+ ' <p>'
+ ' <label>thingString: <input data-bind="value: otherThing.thingString" /></label>'
+ ' <span data-bind="text: otherThing.thingString" />'
+ ' </p>'
+ ' <p data-bind="text: JSON.stringify(ko.unwrap(otherThing))"></p>'
+ '</div>'
});
for displaying data from the two view models.
In the HTML I can successfully use the the component and using a foreach
I can combine the two objects:
<h1>1 component</h1>
<combinedthing-component params="thing: specialThing, otherThing: specialOtherThing"></combinedthing-component>
<h1>Foreach</h1>
<!-- ko foreach: things -->
<div>
<h3 data-bind="text: 'Thing ' + thingNumber()"></h3>
<p>
<label>thingNumber <Input data-bind="value: thingNumber" /></label>
<span data-bind="text: thingNumber" />
</p>
<p>
<label>thingString: <input data-bind="value: $root.otherThings[$index()].thingString" /></label>
<span data-bind="text: $root.otherThings[$index()].thingString" />
</p>
</div>
<!-- /ko -->
but if I try and combine the two - looping thorugh things
with the foreach
and then accessing the otherThings
Array using $index and binding these to the component:
<h1>Many Components</h1>
<!-- ko foreach: things -->
<combinedthing-component params="thing: $data, otherThing: $root.otherThings[$index()]"></combinedthing-component>
<!-- /ko -->
Then while I get an object in otherThing
(as proved by the ko.toJSON binding) its properties are not binding to the input
and span
.
What gives?