I have a rather large ASP.NET MVC web application which uses KnockoutJS extensively throughout. Over the years I’ve created many templates for the application, however they all reside in various web pages using named script tags. It’s almost become unbearable to manage them on the various views. I’d like to figure out a way to consolidate these templates into their own html files so that they are more manageable.
I’d like to know if there are any libraries out there that supports this concept? I don’t want to reinvent the wheel, as I’m sure someone has already ran into this problem in the past and solved it. Here is a quick overview of what I’m dealing with…
Basically, I have a lot of content that resembles the following markup. Notice that I have my templates defined in the same page as my actual content markup:
[[ HOME/INDEX.CSHTML ]]
<h1>Customers</h1>
<div data-bind="template: {name: 'personTmpl', foreach: customers}"></div>
<h1>Products</h1>
<div data-bind="template: {name: 'productTmpl', foreach: products}"></div>
<script type="text/html" id="personTmpl">
Name: <span data-bind="text: name" />
Address: <span data-bind="text: address" />
</script>
<script type="text/html" id="productTmpl">
Description: <span data-bind="text: description" />
Category: <span data-bind="text: category" />
</script>
<script type="text/javascript">
$(function(){
var json = {
customers: [ { name: 'Joe', address: 'Denver, CO' } ],
products: [ { name: 'Skis', category: 'Outdoors' } ]
};
var vm = new CustomViewModel(json);
ko.applyBindings(vm);
});
</script>
[[ END HOME/INDEX.CSHTML ]]
What I’d like to do is store the personTmpl and productTmpl in their own html file and pull them into the view as needed. This would allow me to only have the content markup in my cshtml file. Plus it would enable me to use the templates from anywhere (ie. Customers\Index, Products\Show, Home\Index, etc..).
I would expect that it would require some custom js on each page, but I think this is a small price to pay for cleaning up the clutter and making my templates available to all views. I could see me using some server side tags on each page or something like this (merely an example):
@section templates {
@Content.Template("Person.tmpl", Url)
@Content.Template("Product.tmpl", Url)
}
<h1>Customers</h1>
<div data-bind="template: {name: 'personTmpl', foreach: customers}"></div>
<h1>Products</h1>
<div data-bind="template: {name: 'productTmpl', foreach: products}"></div>
<script type="text/javascript">
$(function(){
var json = @Html.Raw(Json.Encode(ViewBag.PageData)));
var vm = new CustomViewModel(json);
ko.applyBindings(vm);
});
</script>
With storing them into their own templates, I could even query the content dynamically for tooltips and dialogs using old fashion $.get('/tmpl/Person.tmpl', renderFunc).
Again, I don’t mind creating my own implementation, but I’m convinced there is a solution out there already. Anybody?
Thanks in advance!!
My recommendation would be to look at the external template engine here: https://github.com/ifandelse/Knockout.js-External-Template-Engine
It allows you to place your templates in external files, reference them in your binding just as you normally would using the
nameparameter, and uses some conventions or configuration to determine the exact path to find the template file.The external template engine is a pretty robust solution. I have also recently been using
require.jswith itstextplugin for this purpose as well. More info in this answer: knockout.js loading templates at runtimeIf you want to render them in-line, then I suppose a helper function could load the file and wrap it in a script tag with a non-JS type.