Including JavaScript at bottom of page, from Partial Views

前端 未结 2 1305
情深已故
情深已故 2020-12-16 01:16

Let\'s say I have a javascript slide-show in a partial view...

_Slideshow.cshtml:

@{
    ViewBag.Title = \"Slide Show\";
}
相关标签:
2条回答
  • 2020-12-16 02:05

    You could define a section in your layout page for the scripts like this:

    <body>
        <div id="wrapper">
        @RenderBody
        </div>
        <!-- Being a good little web developer, I include my scripts at the BOTTOM, yay!
        -->
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
        @RenderSection("myScripts")
    </body>
    

    Then on your pages you define what goes in that section:

    @{
        ViewBag.Title = "Slide Show";
    }
    <div id="slides">
    </div>
    @section myScripts { //put your scripts here
        <script src="js/slides.min.jquery.js"></script>
        <script type="text/javascript">
        $(function(){
            $('#slides').slides({
                // slide show configuration...
            });
        });
        </script>
    }
    

    Then when the page renders, it will take everything in your section and add it to where it is supposed to go on your layout page (in this case, at the bottom).

    0 讨论(0)
  • 2020-12-16 02:05

    Note: The accepted solution won't work for partial views as the question asks for.

    The Problem

    In the normal flow, you can define the contents for a particular section from inside of the parent view on your ActionResult using a @section SectionName {} declaration. And when that view is finally inserted into its LayoutPage, it can call RenderSection to place those contents anywhere within the page, allowing you to define some inline JavaScript that can be rendered and parsed at the bottom of the page after any core libraries that it depends on like this:

    The problem arises when you want to be able to reuse the full page view inside of a partial view. Perhaps you'd like to also re-use the view as a widget or dialog from inside of another page. In which case, the full Partial View is rendered in its entirety wherever you've placed the call to @Html.EditorFor or @Html.Partial inside of the Parent View like this:

    According to the MSDN Docs on Layouts with Razor Syntax:

    • Sections defined in a view are available only in its immediate layout page.
    • Sections cannot be referenced from partials, view components, or other parts of the view system.
    • The body and all sections in a content page must all be rendered by the layout page

    In that scenario, it becomes tricky to get the script defined into the partial view to the bottom of the page. Per the docs, you can only call RenderSection from the layout view and you cannot define the @section contents from inside of a partial view, so everything gets lumped into the same area and your script will be rendered, parsed, and run from the middle of your HTML page, instead of at the bottom, after any libraries it might depend on.

    The Solution

    For a full discussion of the many ways to inject sections from partial views into your page, I'd start with the following two questions on StackOverflow:

    • Injecting content into specific sections from a partial view with Razor View Engine
    • Using sections in Editor/Display templates

    The varying solutions therein differ on support for nesting, ordering, multiple script support, different content types, calling syntax, and reusability. But however you slice it, pretty much any solution will have to accomplish two basic tasks:

    1. Gradually build script objects onto your request from within any page, partial view, or template, probably leveraging some kind of HtmlHelper extension for reusability.
    2. Render that script object onto your layout page. Since the layout page actually renders last, this is simply emitting the object we've been building onto the master page.

    Here's a simple implementation by Darin Dimitrov

    Add the Helper Extension Methods which will allow you to build arbitrary script objects into the ViewContent.HttpContext.Items collection and subsequently fetch and render them later.

    Utilities.cs

    public static class HtmlExtensions
    {
        public static MvcHtmlString Script(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
        {
            htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
            return MvcHtmlString.Empty;
        }
    
        public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
        {
            foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
            {
                if (key.ToString().StartsWith("_script_"))
                {
                    var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
                    if (template != null)
                    {
                        htmlHelper.ViewContext.Writer.Write(template(null));
                    }
                }
            }
            return MvcHtmlString.Empty;
        }
    }
    

    Then you can use like this within your application

    Build this script objects like this inside of your Partial View like this:

    @Html.Script(
        @<script>
             $(function() {
                 $("#@Html.IdFor(model => model.FirstName)").change(function() {
                     alert("New value is '" + this.value + "'");
                 });
             })
         </script>
    )
    

    And then render them anywhere within your LayoutPage like this:

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
    @Html.RenderScripts()
    
    0 讨论(0)
提交回复
热议问题