Reputation: 46657
I have a viewModel containing child viewModels in an observableArray that is bound to some markup using a foreach binding.
Later in the page life cycle, I need to remove the old viewModel and apply a new one in its place. I do this by calling ko.cleanNode() and then calling applyBindings with the new view model.
For some reason when this happens, all of the child view models end up getting duplicated markup even though the parent observableArray has the correct number of viewModels in it.
I am sure I am just using some knockout functionality incorrectly, but I cannot figure out how to get it working.
Issue is replicated here: http://jsfiddle.net/a7xLxwxh/
Markup:
<div class="container">
<label>RANGES</label>
<div class="rangeContainer" data-bind="foreach: ranges">
<div class="range">
<span>START <br /><span data-bind="text: start"></span></span>
<span>END <br /><span data-bind="text: end"></span></span>
</div>
</div>
</div>
JS:
var ParentViewModel = function (data) {
var self = this;
self.ranges = ko.observableArray([]);
data.Ranges.forEach(function (range) {
self.ranges.push(new RangeViewModel(range));
});
};
var RangeViewModel = function (data) {
var self = this;
self.start = ko.observable(moment(data.Start).format('MM/DD/YYYY'));
self.end = ko.observable(moment(data.End).format('MM/DD/YYYY'));
};
var vm = new ParentViewModel({
Ranges: [{
Start: '/Date(1439438400000)/',
End: '/Date(1439611200000)/'
},
{
Start: '/Date(1439265600000)/',
End: '/Date(1439352000000)/'
}]
});
var element = $('.container')[0];
ko.applyBindings(vm, element);
ko.cleanNode(element);
ko.applyBindings(vm, element);
Upvotes: 1
Views: 291
Reputation: 4651
Use the with
binding in order to swap out view models. cleanNode
is an undocumented method.
<div class="container" data-bind="with: viewModel">
...
</div>
http://jsfiddle.net/a7xLxwxh/3/
Upvotes: 1
Reputation: 49125
Later in the page life cycle, I need to remove the old viewModel and apply a new one in its place.
The better way to replace the view-model is to make the view-model itself an observable:
var vm = ko.observable(new ParentViewModel(
{
Ranges: [{
Start: '/Date(1439438400000)/',
End: '/Date(1439611200000)/'
},
{
Start: '/Date(1439265600000)/',
End: '/Date(1439352000000)/'
}]
}));
ko.applyBindings(vm);
Then when you want to replace it:
vm(new ParentViewModel({
Ranges: [{
Start: '/Date(1439438400000)/',
End: '/Date(1435611200000)/'
}]
}));
See Fiddle
Upvotes: 4