JSFiddle - React, Tailwind, and code Playground
by dzul1983
HTML
<!-- Initial data for the people observableArray -->
<div data-bind="useInitForEach: people">
<p><span data-bind="text: firstName">John</span> <span data-bind="text: lastName">Doe</span></p>
<p><span data-bind="text: firstName">Jane</span> <span data-bind="text: lastName">Doe</span></p>
<p><span data-bind="text: firstName">Frank</span> <span data-bind="text: lastName">Doe</span></p>
</div>
<!-- ko foreach: people -->
<p><span data-bind="text: firstName"></span> <span data-bind="text: lastName"></span></p>
<!-- /ko -->
<p data-bind="text: ko.toJSON(people)"></p>
JavaScript
ko.bindingHandlers.useInitForEach = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext){
var bindingProvider = ko.bindingProvider['instance'];
var children = element.children;
var foreachArray = [];
for(var i=0;i<children.length;i++){
var c = children[i];
var c_children = c.getElementsByTagName('*');
var foreachArrayObj = {};
for(var j=0;j<c_children.length;j++){
var child = c_children[j];
var bindingString = bindingProvider.getBindingsString(child);
if (!bindingString || bindingString.length === 0) {
continue;
}
var bindPropObj = ko.jsonExpressionRewriting.parseObjectLiteral(bindingString.replace(/\s+/g, ''));
if(!bindPropObj){
continue;
}
var val;
var bindType = bindPropObj[0].key;
switch(bindType){ // TODO: add other type value getter
case 'text':
val = child.innerHTML;
break;
}
foreachArrayObj[bindPropObj[0].value] = val;
}
foreachArray.push(foreachArrayObj);
}
// empty observableArray and push new objects in
valueAccessor().removeAll();
for(var k=0;k<foreachArray.length;k++){
valueAccessor().push(foreachArray[k]);
}
// remove init data element node from DOM
element.parentNode.removeChild(element);
// make sure KO doesn't bind children for this element
return { controlsDescendantBindings: true };
}
};
function viewModel(){
this.people = ko.observableArray([]);
}
var viewmodel = new viewModel();
ko.applyBindings(viewmodel);