views:

569

answers:

3

How do I properly register javascript blocks in an ASP.NET MVC 2 (RTM) Editor template?

The specific scenario I'm in is that I want to use Dynarch JSCal2 DateTimePicker for my standard datetime picker, but this question is in general to any reusable javascript package. I have my template working properly now but it has my JS and CSS includes in my master page and I would rather only include these things if I actually need them:

<link rel="stylesheet" type="text/css" href="../../Content/JSCal2-1.7/jscal2.css" />
<link rel="stylesheet" type="text/css" href="../../Content/JSCal2-1.7/border-radius.css" />
<script type="text/javascript" src="../../Scripts/JSCal2-1.7/jscal2.js"></script>
<script type="text/javascript" src="../../Scripts/JSCal2-1.7/lang/en.js"></script>

So obviously I could just put these lines into my template, but then if I have a screen that has 5 DateTimePickers, then this content would be duplicated 5 times which wouldn't be ideal. Anyways, I still want my View's Template to trigger this code being put into the <head> of my page.

While it is completely unrelated to my asking this question, I thought I'd share my template on here (so far) in case it's useful in any way:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DateTime>" %>

<%= Html.TextBoxFor(model => Model) %>
<input type="button" id="<%= ViewData.TemplateInfo.GetFullHtmlFieldId("cal-trigger") %>" value="..." />

<script type="text/javascript">
    var <%= ViewData.TemplateInfo.GetFullHtmlFieldId("cal") %> = Calendar.setup({
        trigger       : "<%= ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty) %>",
        inputField    : "<%= ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty) %>",
        onSelect      : function() { this.hide(); },
        showTime      : 12,
        selectionType : Calendar.SEL_SINGLE,
        dateFormat    : '%o/%e/%Y %l:%M %P'
    });
</script>
+2  A: 

I usually add a script placeholder in my master page that is overridden by views:

Master:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html>
<head>
    <title></title>
    <asp:ContentPlaceHolder ID="Styles" runat="server" />
</head>
<body>
    <asp:ContentPlaceHolder ID="MainContent" runat="server" />
    <script type="text/javascript" src="scriptAvailableToAllPages.js"></script>
    <asp:ContentPlaceHolder ID="Scripts" runat="server" />
</body>
</html>

View:

<%@ Page Language="C#" 
         MasterPageFile="~/Views/Shared/Site.Master" 
         Inherits="System.Web.Mvc.ViewPage<Ns.MyModel>" %>

<asp:Content ID="indexScripts" ContentPlaceHolderID="Scripts" runat="server">
    <script type="text/javascript" src="specific.js"></script>
</asp:Content>

<asp:Content ID="MainContent" ContentPlaceHolderID="MainContent" runat="server">
    <% using (Html.BeginForm()) { %>
        <%= Html.EditorFor(x => x.Date1) %>
        <%= Html.EditorFor(x => x.Date2) %>
        <%= Html.EditorFor(x => x.Date3) %>
        <input type="submit" value="OK" />
    <% } %>
</asp:Content>

Notice how the editor template is included for three different properties of the model but the required scripts are included only once.

Darin Dimitrov
Makes sense, but how would my Editor Templates hook into that?
Jaxidian
The editor templates rely on some script module/plugin to be included in the page. In your case I guess that this script contains the `Calendar.setup` function. The main view takes care to include this script. In the example I provided all scripts are included at the end of the page (see master file) but if you prefer you could move them to the `head` section.
Darin Dimitrov
I don't want my views to have to deal with these scripts, though. I want my views to be completely unconcerned with my templates' implementations. My plan is to use this non-ideal javascript "control" until I have a better JQuery or MVC-based "control" to use as my datetimepicker. And when that time comes, I don't want to have to edit any files other than this one editor template. SOC is the goal here - my view shouldn't need to know what js files my template depends upon.
Jaxidian
Unfortunately the WebForms view engine prevents you from overriding sections defined in master from partial views. Other view engines such as NVelocity or Brail allow you to achieve this.
Darin Dimitrov
So there are no equivalents to ScriptManager.Registerxxx functions for MVC Templates?
Jaxidian
This also does not work for partial views.
xanadont
+2  A: 

I Build a simple scritp Manage to handle this, unfortunately i haven't done it for CSS check out Asp.Net MVC Manager for javascript include and Css files . Unfortunately, it's not working proeprly for CSS, for javascript i simply just had them at the bottom of my master file, but CSS must be in the head tag, i haven't found a way yet to do that...

But using that I've been able to had script in a custom HtmlHelper, DatePicker which I use with a template DateTime.ascx.

moi_meme
Thanks for this info! It sounds like you're wanting to do exactly what I want to do. I'll look into this and share any improvements I might have.
Jaxidian
After trying this out, I simply cannot get the CSSManager to work and I don't see how it is possible.
Jaxidian
That's what I said in my response, it's more complicated for CSS... And I didn't do it in my code, it's only working when you add it in the header tag of a view
moi_meme
I know your implementation of it is not working. I meant I could not figure out how to get it to work. The primary problem I see is caused by the stateless nature of this, and what we're trying to do with the CSS requires state, and deferred execution.
Jaxidian
+1  A: 

The telerik web asset manager allows you to accomplish what you want and is open source.

Brian
Nice! Thank you!
Jaxidian