Populate a Razor Section From a Partial

前端 未结 12 1454
不知归路
不知归路 2020-11-27 11:23

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 mid

相关标签:
12条回答
  • 2020-11-27 11:43

    The more elegant way to do this is to move partial view scripts into separate file and then render it in Scripts section of view:

    <h2>This is the view</h2>
    
    @Html.RenderPartial("_Partial")
    
    @section Scripts
    {
        @Html.RenderPartial("_PartialScripts")
    
        <script type="text/javascript">
            alert("I'm a view script.");
        </script>
    }
    

    The partial view _Partial.cshtml:

    <p>This is the partial.</p>
    

    The partial view _PartialScripts.cshtml with scripts only:

    <script type="text/javascript">
        alert("I'm a partial script!");
    </script>
    
    0 讨论(0)
  • 2020-11-27 11:44

    Base on the answer from Mr Bell And Shimmy above, I add on extra function for Bundle script.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Text;
    using System.Web.Mvc;
    namespace ABC.Utility
    {
    public static  class PartialViewHelper
    {
        public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
        {
            var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
            if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
            if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
            return null;
        }
    
        public static string RequireBundleStyles(this HtmlHelper html, string bundleName)
        {
            var a = System.Web.Optimization.Styles.Render(bundleName);
            var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString;
            if (requiredStyles == null) HttpContext.Current.Items["RequiredStyles"] = requiredStyles = a;
            return null;
        }
    
        public static string RequireBundleScripts(this HtmlHelper html, string bundleName)
        {
            var a=System.Web.Optimization.Scripts.Render(bundleName);
            var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString;
            if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = a;
            return null;
        }
    
        public static HtmlString EmitRequiredBundleStyles(this HtmlHelper html)
        {
            var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString;
            if (requiredStyles == null) return null;
            return MvcHtmlString.Create(requiredStyles.ToHtmlString()) ;
        }
    
        public static HtmlString EmitRequiredBundleScripts(this HtmlHelper html)
        {
            var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString;
            if (requiredScripts == null) return null;
            return MvcHtmlString.Create(requiredScripts.ToHtmlString());
        }
    
        public static HtmlString EmitRequiredScripts(this HtmlHelper html)
        {
            var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
            if (requiredScripts == null) return null;
            StringBuilder sb = new StringBuilder();
            foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
            {
                sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
            }
            return new HtmlString(sb.ToString());
        }
        public class ResourceInclude
        {
            public string Path { get; set; }
            public int Priority { get; set; }
        }
    }//end class
    }// end namespace  
    

    Sample on PartialView :- @Html.RequireBundleStyles("~/bundles/fileupload/bootstrap/BasicPlusUI/css"); @Html.RequireBundleScripts("~/bundles/fileupload/bootstrap/BasicPlusUI/js");

    Sample on MasterPage :- @Html.EmitRequiredBundleStyles()

    0 讨论(0)
  • 2020-11-27 11:46

    Use @using(Html.Delayed()){ ...your content... } extensions from answer https://stackoverflow.com/a/18790222/1037948 to render any content (scripts or just HTML) later in the page. Internal Queue should ensure correct ordering.

    0 讨论(0)
  • 2020-11-27 11:49

    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:

    public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
    {
        var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
        if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
        if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
        return null;
    }
    
    public static HtmlString EmitRequiredScripts(this HtmlHelper html)
    {
        var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
        if (requiredScripts == null) return null;
        StringBuilder sb = new StringBuilder();
        foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
        {
            sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
        }
        return new HtmlString(sb.ToString());
    }
    public class ResourceInclude
    {
        public string Path { get; set; }
        public int Priority { get; set; }
    }
    

    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

    0 讨论(0)
  • 2020-11-27 11:52

    This functionality is also implemented in ClientDependency.Core.Mvc.dll. It provides the html helpers: @Html.RequiresJs and @Html.RenderJsHere(). Nuget package: ClientDependency-Mvc

    0 讨论(0)
  • 2020-11-27 11:58

    You could have a second partial that is only in charge of injecting the necessary javascript. Place several scripts in there around @if blocks, if you want:

    @model string
    @if(Model == "bla") {
        <script type="text/javascript">...</script>
    }
    
    @else if(Model == "bli") {
        <script type="text/javascript">...</script>
    }
    

    This could obviously be cleaned up a bit, but then, in the Scripts section of your view:

    @section Scripts
    {
        @Html.Partial("_Scripts", "ScriptName_For_Partial1")
    }
    

    Again, it might not win a beauty prize but it will work.

    0 讨论(0)
提交回复
热议问题