Reputation: 5283
My web application is ASP.NET MVC4 with Razor and Knockout.js. The view model hierarchy is becoming rather deep and complicated and I am moving more towards using nested Knockout templates for the corresponding views (each with a for/each for its child templates, etc) rather than monolithic slabs of HTML.
Something that annoys me is that when using the Knockout template definition syntax of <script type="text/html" id="scary-template">
the contents loses its Razor syntax highlighting in Visual Studio because it is interpreted as script. The templates are complex enough without the text all being plain black as well.
Some approaches I have considered are using Html.Raw to output the opening and closing script tags, or HtmlHelper extensions like Html.BeginKOTemplate(id) .
I'm interested to hear how other ASP.NET MVC folks approach this. Am I being pedantic? In any case the next developer who needs to pick this solution up will probably thank me for caring.
Upvotes: 1
Views: 1556
Reputation: 23935
Use Razors partial views to overcome this problem.
<script type="text/html" id="launchTemplate">
@Html.Partial("Templates/_LaunchView", null)
</script>
The above syntax allows you to keep your templates in a separate file. In that file you will have the full razor syntax highlighting (not to mention reformatting)
Upvotes: 0
Reputation: 1637
Personally, I use the knockout external template engine to load templates dynamically from other files. This has its own set of advantages and disadvantages, but a nice side effect is that the templates can be stored in .html files and do not need to wrapped at all - preserving all the syntax highlighting. Instead of just using the id of the script tag, the external template engine will look for files in whatever directory you tell it with the template name (such as mytemplate.html) as well.
In my experience, this also tends to make the project more organized and helps fosters code reuse between projects. The only down side is the added latency from downloading more files - which could actually increase performance through lazy loading since it will only load templates when they're needed (and will not make multiple requests for the same template)
Upvotes: 1
Reputation: 6679
Just a quick suggestion, separate JavaScript and Razor like I described here: https://stackoverflow.com/a/11109799/538387
Upvotes: 0
Reputation: 5283
I've gone with creating an HtmlHelper extension which returns a KnockoutTemplate class which implements IDisposable:
public static KnockoutTemplate KnockoutTemplate(this HtmlHelper htmlHelper, string templateID)
{
return new KnockoutTemplate(templateID, htmlHelper.ViewContext.Writer);
}
public class KnockoutTemplate: IDisposable
{
private TextWriter _textWriter;
private bool _disposed;
public KnockoutTemplate(string templateID, TextWriter textWriter)
{
_textWriter = textWriter;
_textWriter.WriteLine(String.Format("<script type=\"text/html\" id=\"{0}\">", templateID));
}
public void EndTemplate()
{
Dispose(true);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
_disposed = true;
_textWriter.WriteLine("</script>");
}
}
}
Used like so:
@using (Html.KnockoutTemplate("sum-assured-template"))
{
<div>Template markup...</div>
}
On further thought I didn't like the idea that with a div, the markup of the template itself would be interpreted as a template instance by the browser, so I've stuck with the script block approach for now, but at least I can change all instances in one place later if I want.
Upvotes: 1
Reputation: 16688
I don't use Visual Studio, but I have some suggestions that could work for you.
Starting with Knockout 2.1, you can define a template using the textarea
tag, which will support syntax highlighting in many editors (including two I use, phpDesigner and Notepad++). To make sure the textarea
doesn't actually display on the page, it must have the display:none
style (or be in a container with that style).
<textarea id="mytemplate" style="display:none">
<div>template content</div>
</textarea>
or
<div style="display:none">
<textarea id="mytemplate">
<div>template content</div>
</textarea>
</div>
You can also use any tag such as div
to define a template. But this adds some overhead. First, the template content will be parsed (and possibly modified) by the browser. Second, it will be parsed by Knockout unless you instruct it otherwise. You can do this by passing a container node to applyBindings
that doesn't contain the template nodes, or by creating a custom binding that bypasses bindings for the template (see allowBindings
here). You will still need the display:none
style, of course.
<div style="display:none" data-bind="allowBindings:false">
<div id="mytemplate">
<div>template content</div>
</div>
</div>
Upvotes: 5