1. ホーム
  2. javascript

[解決済み] 部分テンプレートからRazorセクションを生成する

2022-10-15 18:16:55

質問

これを行おうとする私の主な動機は、パーシャルによってのみ必要とされるJavascriptを、パーシャルがレンダリングされるページの中央ではなく、残りのJavascriptと一緒にページの下部に表示させることです。

私がやろうとしていることの単純化された例です。

本文の直前にScriptsセクションがあるレイアウトです。

<!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>

このレイアウトを使ったビューの例です。

<h2>This is the view</h2>

@{Html.RenderPartial("_Partial");}

@section Scripts {
<script type="text/javascript">
        alert("I'm a view.");
</script>
}

そして、これがビューからレンダリングされるパーシャルです。

<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>
}

この例では、ビューで指定されたマークアップはセクションに配置されますが、パーシャルからのマークアップはそうではありません。Razor でパーシャルビューからセクションに入力することは可能でしょうか?もしそうでなければ、パーシャルだけが必要とする Javascript をグローバルに含めずにページの一番下に持ってくる他の方法は何でしょうか?

どのように解決するのですか?

私がこれに対処した方法は、HtmlHelper クラスにいくつかの拡張メソッドを書くことです。これにより、パーシャルビューでスクリプトが必要であることを示すことができ、タグを書き込むレイアウトビューで、必要なスクリプトを発行するために私のヘルパーメソッドを呼び出すことができます。

以下がそのヘルパーメソッドです。

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; }
}

これを配置したら、パーシャルビューはただ @Html.RequireScript("/Path/To/Script") .

そして、レイアウトビューのヘッドセクションで @Html.EmitRequiredScripts() .

これの付加的な利点は、重複したスクリプトの要求を除外できることです。あるスクリプトを必要とする複数のビューや部分的なビューがある場合、そのスクリプトは一度だけ出力されると安全に仮定することができます。