Knockout JS with observableArray foreach working
forEach binding of an observableArray only passes data on to
by brianlmerritt
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<p>Input DataHere</p>
<ul data-bind='foreach: list'>
<li>
<input data-bind='value: $rawData'/>
</li>
</ul>
<br />
<p>Output - Bind with Raw Data</p>
<ul data-bind='foreach: list'>
<li>
<span data-bind='text: $data'></span>
</li>
</ul>
<br />
<p>Output - Bind with Just Data - It still works because the data input is bound with $rawData</p>
<ul data-bind='foreach: list'>
<li>
<span data-bind='text: $rawData'></span>
</li>
</ul>
<br />
<p>Observable Array with ticking changes of observable objects</p>
<ul data-bind='foreach : observableArrayList'>
<li>
<p data-bind='text : itemNumber'></p>
<p data-bind='text : itemText'></p>
</li>
</ul>
<br />
<p>Observable Array with non-observable changing objects</p>
<ul data-bind='foreach : observableArrayList2'>
<li>
<p data-bind='text : itemNumber'></p>
<p data-bind='text : itemText'></p>
</li>
</ul>
CSS
body {margin-left:20px;
margin-top:20px}
JavaScript
observableThing = {
itemNumber : 1,
itemText : 'This Thing'
}
//KO ViewModel
vm = {
list: [
ko.observable('123'),
ko.observable('456')
],
observableArrayList : ko.observableArray(
[
ko.observable(observableThing),
ko.observable(observableThing),
ko.observable(observableThing),
ko.observable(observableThing)
]
),
observableArrayList2 : ko.observableArray(
[
observableThing,
observableThing,
observableThing,
observableThing,
]
)
};
ko.applyBindings(vm);
//Prepare to run timer to update observable arrays
this.itemToChange = 0 ;
self= this;
var myTrigger = setInterval(function(){
console.info('Timer Triggered');
myChanger(self);
},1000);
//Update the observable arrays
function myChanger(self) {
console.info(self.itemToChange);
//First change the observableArray with observables (Objects in this case)
var observableToChange = vm.observableArrayList()[self.itemToChange];
var observableToChangeValues = observableToChange();
var itemNumber = observableToChangeValues.itemNumber + self.itemToChange + 1;
var itemText = observableToChangeValues.itemText ;
if (itemText === 'This Thing') {
itemText = 'That Thing';
} else {
itemText = 'This Thing';
}
observableToChange({itemNumber: itemNumber, itemText : itemText}); //Update the observable
vm.observableArrayList().forEach( function(item) {
console.info(item());
});
//Next change the observableArray with plain objects
var objectToChange2 = vm.observableArrayList2()[self.itemToChange];
var itemNumber = objectToChange2.itemNumber + self.itemToChange + 1;
var itemText = objectToChange2.itemText ;
if (itemText === 'This Thing') {
itemText = 'That Thing';
} else {
itemText = 'This Thing';
}
vm.observableArrayList2()[self.itemToChange] = {itemNumber: itemNumber, itemText : itemText}; // Update the observableArray data
vm.observableArrayList2().forEach(...