Reputation:
I've found engines, plugins and functions to load external templates, but I'm wondering if there's a simpler way to do it. Something like this?
templates.html
<script id="testTemplate" type="text/html">
<div>this is a div</div>
</script>
index.html
<div id="templateContainer"></div>
<script>
$(document).ready(function() {
$("#templateContainer").load("templates.html");
}
</script>
Will this work? Are there any "gotchas"?
Upvotes: 22
Views: 23983
Reputation: 27
I've finally been able to piece together a lazy template loader with the help of binding handlers. Wanted to share.
Lazy loader
markupLoader = {
templateDictionary: {},
loadMarkup: function (element, value, bindingContext) {
if (!this.templateDictionary[value]) {
this.templateDictionary[value] = $.get(value);
}
this.templateDictionary[value].done(function (template) {
$(element).html(template);
$(element).children().each(function (index, child) {
ko.applyBindings(bindingContext, child);
});
});
}
};
Binding handler
ko.bindingHandlers.htmlUrl = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
let value = ko.unwrap(valueAccessor());
markupLoader.loadMarkup(element, value, bindingContext);
return { controlsDescendantBindings: true };
}
};
Upvotes: 1
Reputation: 428
I created a new binding to load html from url and apply binding on it
ko.bindingHandlers.htmlUrl = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
$(element).load(valueAccessor(), function () {
$(element).children().each(function (index, child) {
ko.applyBindings(bindingContext.$data, child);
});
});
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
}
};
usage
<div data-bind="htmlUrl : <url>">
</div>
Upvotes: 3
Reputation: 16688
Here's what I use to load a template file that contains a collection of templates:
var loadTemplateCollection = function(file, success) {
$.get('templates/' + file + '.html', function(templates) {
$('body').append('<div style="display:none">' + templates + '<\/div>');
success();
});
};
Here's an example where I use this function:
self.loadPage = function () {
if (!self.isLoaded()) {
loadTemplateCollection('uploadwizard', function() {
self.isLoaded(true);
self.uploadWizard();
});
}
}
Your view would look something like this (the if
is important):
<div data-bind="template: {'if': isLoaded, name: 'uploadwizard', data: wizard}"></div>
Upvotes: 29
Reputation: 8987
This is what I am using to load the new page view. I think it is pretty simple to use :
var template = 'template.html';
var targetID = 'container';
var partialVM = {data : 1};
var load = function (template, targetID, partialVM) {
$.ajax(template, { async: false })
.success(function (stream) {
$('#' + targetID).html(stream);
ko.applyBindings(partialVM, document.getElementById(targetID));
}
);
};
But in my html templates I didn't have the script element, just a simple div as root element.
I hope it helps.
Upvotes: 6