KO lazy template load test

by whelkaholism

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<a data-bind="click: load1">load1</a> |
<a data-bind="click: load2">load2</a> |
<a data-bind="click: load3">load no template</a>
<hr/>
<b>Explicit model</b>
<div data-bind="lazy: { model: ReportData, template: ReportTemplate }">
</div>
<hr/>
<b>Implicit model</b>
<!-- ko with: ReportData -->
<div data-bind="lazy: $parent.ReportTemplate"></div>
<!-- /ko -->

JavaScript

ko.bindingHandlers.lazy = {
	init:
		function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
		{		
			return { controlsDescendantBindings: true }            
		},		
	update: 
		function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
		{		
			// Get current value of supplied value
			var field = f_valueaccessor();
			var o = ko.unwrap(field);            
			
			var model, template, options = {};
			
			if(o.model)
			{			
				model = ko.unwrap(o.model);
                template = ko.unwrap(o.template);
				options = o.options || options;
			}
			else
			{
					model = ko.unwrap(bindingcontext.$data);
					template = o;
			}
			
			var ctx = bindingcontext;
			
			ctx = bindingcontext.createChildContext(model);
									
			$(el).empty();
			
			if(model && template)
			{
				var els = $(template).appendTo(el);
		
				console.log(['update', o.model ? 'explicit' : 'implicit', model, template, els]);
				
				ko.applyBindingsToDescendants(ctx, el);
			}
		}
};

function ReportDataModel()
{
    this.Items = ko.observableArray([
        { ID:1, Label:'Widgets', Amount:'£10000.00' },
        { ID:2, Label:'Wodgets', Amount:'£20000.00' },
        { ID:3, Label:'Gadgets', Amount:'£50000.00' },
        { ID:4, Label:'Gidgets', Amount:'£15400.00' },
        { ID:5, Label:'Bodgets', Amount:'£10345.00' },
        { ID:6, Label:'Badgets', Amount:'£23000.00' },
        { ID:7, Label:'Badgers', Amount:'£44000.00' },
        { ID:8, Label:'Bodgers', Amount:'£10555.00' }
    ]);
}

function Model()
{
    this.ReportData = ko.observable();
    this.ReportTemplate = ko.observable();
    
    this.load1 = function()
    {        
        this.ReportTemplate(
            '<ul data-bind="foreach: Items"><li>' + 
            '<b data-bind="text: ID"></b>' + 
            '<span data-bind="text: Label"></span>' + 
            '<span data-bind="text: Amount"></span>' + 
            '</li></ul>'
        );
        this.ReportData(new ReportDataModel());
    };
...