depend
standalone depend handler
by Jaak Kütt
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.3.0.debug.js"></script>
<div class="root" data-bind="template: { name: function(data){return displayMode(data);}, foreach: items }">
</div>
<script type="text/html" id="default">
<div class="item" data-bind="'if':id">
<div data-bind="html:content"></div>
<div data-bind="depend: ['pos1']">
<div class="red" data-bind="template: { name: function(data){return displayMode(data);}, foreach: children().pos1 }"></div>
</div>
<div>
<div data-bind="depend: ['pos2']">
<div class="green" data-bind="template: { name: function(data){return displayMode(data);}, foreach: children().pos2 }"></div>
</div>
<div data-bind="depend: ['pos3']">
<div class="blue" data-bind="template: { name: function(data){return displayMode(data);}, foreach: children().pos3 }"></div>
</div>
</div>
</div>
</script>
<script type="text/html" id="first">
<div class="item fat" data-bind="'if':id">
<div data-bind="html:content"></div>
<div data-bind="depend: ['pos2']">
<div class="red" data-bind="template: { name: function(data){return displayMode(data);}, foreach: children().pos2 }"></div>
</div>
</div>
</script>
CSS
.item{border:1px solid black;padding:10px;margin:10px;}
.red {color :red;}
.green {color: green;}
.blue {color: blue;}
.fat{border-width:2px;}
JavaScript
window.displayMode=function (module){
return (module.template() && document.getElementById(module.template()))?module.template():'default';
}
function ChildArray(){
this.addChild=function(pdata,cdata){
if(typeof pdata==='string'){
if(!this.hasOwnProperty(pdata)) this[pdata]=ko.observableArray([]);
if(!cdata) return;
if(Object.prototype.toString.call(cdata) === '[object Array]'){
for(c in cdata) this[pdata].push(cdata[c]);
}else{
this[pdata].push(cdata);
}
}else if(typeof pdata==='object'){
for(p in pdata) this.addChild(p,pdata[p]);
}
}
}
ko.bindingHandlers.depend = {
'update': function(e, vA, aBA, vM, bC) {
var i = ko.utils.unwrapObservable(vA());
//make the following function extend template AND add a dependency check for positions used in template AND pass on a porper binding context!
if(!bC.$data.hasOwnProperty(i[0]) || typeof bC.$data[i[0]] !== 'function'){
var existing = bC.$data.children();
existing[i[0]]=ko.observableArray([]);
bC.$data.children(existing);
}
}
};
function ViewChild(id){
this.id=ko.observable(id);
this.content=ko.observable('initial content for '+id);
this.children=ko.observable(new ChildArray);
this.template=ko.observable();
}
var child1=new ViewChild(1);
var child2=new ViewChild(2);
var child3=new ViewChild(3);
var child4=new ViewChild(4);
var child5=new ViewChild(5);
var MyViewModel={};
MyViewModel.items=ko.observableArray([]);
MyViewModel.items().push(child1);
ko.applyBindings(MyViewModel);
child1.children().addChild('pos3',[child3,child4]);
child3.children().addChild({'pos2':child5,'pos1':[new ViewChild(6),new ViewChild(7)]});
setTimeout(function(){
//child3.template('first');
},1000);