I think dropping the script into a .js file and referencing it on your page is the most fun and neat approach to this problem.
If you were looking for a less neat solution, you could add a couple HtmlHelper extensions to add register dependencies as the templating engine encounters them, then print out a bunch of script tags at the end of the page.
private const string requiredJavascriptIncludesContextItemsKey = "requiredJavascriptIncludesContextItemsKey";
public static void Require(this HtmlHelper html, string src)
{
var collection = (HashSet<string>) html.ViewContext.HttpContext.Items[requiredJavascriptIncludesContextItemsKey] ?? new HashSet<string>();
collection.Add(src);
html.ViewContext.HttpContext.Items[requiredJavascriptIncludesContextItemsKey] = collection;
}
public static HtmlString RequiredJavascriptIncludes(this HtmlHelper html)
{
var sb = new StringBuilder();
foreach (var src in (HashSet<string>) html.ViewContext.HttpContext.Items[requiredJavascriptIncludesContextItemsKey] ?? new HashSet<string>())
{
sb.Append(string.Format("<script type='text/javascript' src='{0}></script>", src));
}
return new HtmlString(sb.ToString());
}
You could call the @Html.Require
method within any template. In your case, it'd be like this:
@model Nullable<DateTime>
@{
var metadata = ModelMetadata.FromStringExpression("", ViewData);
string value;
if(!String.IsNullOrEmpty(metadata.EditFormatString)) {
if(Model.HasValue) {
value = String.Format(metadata.EditFormatString, Model.Value);
}
else {
value = metadata.NullDisplayText;
}
}
else {
value = Model.ToString();
}
}
@Html.TextBox("", value, new { @class = "textBoxDate" })
@Html.Require(Html.Content("scripts/datepicker.js"))
Then, at the bottom of your base template page, you'd make the call to @Html.RequiredJavascriptIncludes()
and all your js dependencies you've registered will be rendered as script tags at the end of the html document.