0

I am tired to google around and ddn't found the exact answer.

I know I can pass date from view to template by additionalViewData parameter of .EditorFor() or .DisplayFor() but I want a data back from template!

I have Date.cshtml in my ~/Views/Shared/EditorTemplates/. My model property already have something like this:

public class Person
{
    [DisplayFormat(DataFormatString = "{0:d}")]
    [DataType(DataType.Date)]
    public Nullable<DateTime> BirthDate { get; set; }
}

and the view:

@Html.EditorFor(model => model.BirthDate)

Now I want only to load datepicker script when ever the view uses the date template. So I try to use RequireDatePicker like this in my template:

@model DateTime?
@Html.TextBox(...)
@{ViewBag.RequireDatePicker = true;}

and in the bottom of _Layout.cshtml:

    @Scripts.Render("~/bundles/jquery")
    @if (ViewBag.RequireDatePicker == true)
    {
        <script type="text/javascript">
            if (!Modernizr.inputtypes.date) {
                // Todo: use Modernizr.load
                $(function () {
                    $("input[type='date']").datepicker();
                });
            }
        </script>
    }

The problem is I just realize ViewBag/ViewData has a different context from the view/partial and the display/editor template. What is the best way to do this?


Fix I can pass data from template back to view by route data like this:

@{ViewContext.RouteData.DataToken["requireDatePicker"] = true;}

However I end-up not passing the data but just this:

  1. Have bundle "~/bundles/jqueryui" that

    • remove jquery ui date picker feature from it (and move to "~/bundles/jqueryui-datepicker")
    • include a Modernizr.inputtypes.date check and Modernizr.load to load "~/bundles/jqueryui-datepicker"
  2. No need to modify _layout.cshtml to check for RequireDatePicker. @Scripts.Render("~/bundles/jquery") and @Scripts.Render("~/bundles/jqueryui") is enough sinec Modernizr.load is already included.

  3. No need to pass RequireDatePicker from Date.cshtml to view or _Layout.cshtml as Modernizr.load

CallMeLaNN
  • 8,328
  • 7
  • 59
  • 74

1 Answers1

0

You could create dynamic javascript bundles like outlined in the following article

http://neimke.blogspot.co.nz/2011/12/composing-child-views-with-bundles.html

basically your editorfor template calls the following code

@{
  var bundle = Microsoft.Web.Optimization.BundleTable.Bundles.GetRegisteredBundles()
    .Where(b => b.TransformType == typeof(Microsoft.Web.Optimization.JsMinify))
    .First();

  bundle.AddFile("~/Scripts/DatePicker.js");
}

but you may want to replace the Where clause with one that finds a specific bundle instead, maybe one specifically for including javascript for child views.

If you wanted to go nuts, you could probably extend the razor view engine or WebViewPage to look for matching View.cshtml.js to every view that is rendered and add it to a bundle.

Betty
  • 9,109
  • 2
  • 34
  • 48
  • Seems like a nice solution to combine with bundle feature but I loose the HTML5 browser native date picker. One more thing to consider is the caching the bundled files for `"~/bundles/jqueryui"`. I think content for bundled script should be the same for one URL. – CallMeLaNN Oct 19 '12 at 03:26
  • put it into a new bundle specific to the page rather than the jqueryui one. I don't believe you can create a new bundle on the fly. You shouldn't lose the HTML5 browser native date picker, you should still be able to do the modernizr check. – Betty Oct 19 '12 at 03:50
  • Actually add new bundle on the fly work but you are right, it is not supported and not to be designed in that way. I heard somewhere because of web farm support and bundling should be created only at app start. I already update the question on what I did. – CallMeLaNN Oct 21 '12 at 20:45