My main motivation for trying to do this is to get Javascript that is only required by a partial at the bottom of the page with the rest of the Javascript and not in the middle of the page where the partial is rendered.
Here's a simplified example of what I'm trying to do:
Here is the layout with a Scripts section right before the body.
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
</head>
<body>
@RenderBody()
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
@RenderSection("Scripts", false)
</body>
</html>
Here's an example view using this layout.
<h2>This is the view</h2>
@{Html.RenderPartial("_Partial");}
@section Scripts {
<script type="text/javascript">
alert("I'm a view.");
</script>
}
And here's the partial being rendered from the view.
<p>This is the partial.</p>
@* this never makes it into the rendered page *@
@section Scripts {
<script type="text/javascript">
alert("I'm a partial.");
</script>
}
In this example, the markup specified in the view is placed into the section, but the markup from the partial is not. Is it possible to populate a section from a partial view with Razor? If not, what are some other methods of getting Javascript that's only needed by partials at the bottom of the page without including it globally?
You can create a new
Layout
page and wrap the PartialView inside of a Full View that is responsible for rendering the contents and also any library sections.For example, let's say I have the following code:
HomeController.cs
When the Full Page view is rendered, it's typically renderedby merging two files:
About.cshtml
_Layout.cshtml
(or whatever is specified in _ViewStart or overridden in the page)Now, suppose you wanted to Render
About.cshtml
as a Partial View, perhaps as modal window in response to AJAX call. The goal here being to return only the content specified in the about page, scripts and all, without all the bloat included in the_Layout.cshtml
master layout (like a full<html>
document).You might try it like this, but it won't come with any of the section blocks:
Instead, add a simpler layout page like this:
_PartialLayout.cshtml
Or to support a modal window like this:
_ModalLayout.cshtml
Then you can specify a custom Master View in this controller or any other handler that you want to render the contents and scripts of a view simultaneously
The way I dealt with this is to write a couple extension methods to the HtmlHelper class. That allows partials views to say that they require a script, and then in the layout view that writes the tag I call to my helper method to emit the required scripts
Here are the helper methods:
Once you have that in place your partial view just needs to call
@Html.RequireScript("/Path/To/Script")
.And in the layout view's head section you call
@Html.EmitRequiredScripts()
.An added bonus of this is that it allows you to weed out duplicate script requests. If you have multiple views/partial views that need a given script you can safely assume that you will only output it once
Install the Forloop.HtmlHelpers nuget package - it adds some helpers for managing scripts in partial views and editor templates.
Somewhere in your layout, you need to call
This will be where any script files and script blocks will be outputted in the page so I would recommend putting it after your main scripts in the layout and after a scripts section (if you have one).
If you're using The Web Optimization Framework with bundling, you can use the overload
so that this method is used for writing out script files.
Now, anytime you want to add script files or blocks in a view, partial view or template, simply use
The helpers ensure that only one script file reference is rendered if added multiple times and it also ensures that script files are rendered out in an expected order i.e.
Partial views cannot participate in their parent views' sections.
Base on the answer from Mr Bell And Shimmy above, I add on extra function for Bundle script.
Sample on PartialView :- @Html.RequireBundleStyles("~/bundles/fileupload/bootstrap/BasicPlusUI/css"); @Html.RequireBundleScripts("~/bundles/fileupload/bootstrap/BasicPlusUI/js");
Sample on MasterPage :- @Html.EmitRequiredBundleStyles()