Reputation: 211
My viewModel consist of observable array with observable elements.
// viewmodel
var viewModel = function () {
this.o = ko.observableArray();
for (var i = 0; i < 3; i++)
this.o.push(ko.observable(0));
};
I need to change the values of these elements. And for this purpose I create the component. Simple example of it is below:
//custom element <component>
ko.components.register("component", {
viewModel: function (params) {
var self = this;
this.value = params.value;
console.log("init component");
this.i = 1;
this.change = function () {
self.value(self.i++);
console.log("change to " + self.value());
}
},
template: "<span data-bind='text: value'></span> <button data-bind='click:change'>Change</button>"
});
This component can change value of observable element which come in params.value.
My view is very simple:
<!--ko foreach:o-->
<component params="value: $rawData"></component>
<!--/ko-->
Full example: http://jsfiddle.net/tselofan/xg16u5cg/7/ Problem is when value of observable element in observable array is changed, component is rendered again, because it is located inside foreach binding. You can see this in logs. What the best practice can I use in this situation? Thank you
Upvotes: 3
Views: 1576
Reputation: 43881
Knockout-Repeat (https://github.com/mbest/knockout-repeat) is an iterative binding that does not create a new binding context, and has a foreach
mode, so it should work as you expect with your component.
Upvotes: 1
Reputation: 4641
The component is being recreated each time the number changes because the context of the component is the number.
http://jsfiddle.net/Crimson/xg16u5cg/8/
<!-- ko foreach: o -->
<component params="value: $data.myNumber"></component>
<!-- /ko -->
//Test how components work in foreach binding
//custom element <component>
ko.components.register("component", {
viewModel: function (params) {
var self = this;
this.value = params.value;
console.log("init component");
this.i = 1;
this.change = function () {
self.value(self.i++);
console.log("change to " + self.value());
}
},
template: "<span data-bind='text: value'></span> <button data-bind='click:change'>Change</button>"
});
// viewmodel
var viewModel = function () {
this.o = ko.observableArray();
for (var i = 0; i < 3; i++)
this.o.push({myNumber: ko.observable(0)});
};
ko.applyBindings(new viewModel());
Upvotes: 1