質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.35%

  • ASP.NET

    389questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • MVC

    171questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

部分ビューでのJavaScriptを有効にする方法

解決済

回答 3

投稿 2017/11/24 11:40 ・編集 2017/11/24 15:16

  • 評価
  • クリップ 0
  • VIEW 410

lain

score 116

前提・実現したいこと

「ASP.NET MVC 5」での開発を最近始めたばかりです。

RenderSectionの動きがもう一つ良く分からないですが。
下記コードのように部分ビュー(_TopixView.cshtml)内でJavaScriptを書いているのですが、
部分ビュー内のJavaScriptが有効になりません。

Index.cshtml内のJavaScriptは有効になっています。

jsファイルを作成し、BundleConfig.csで追記することで動作は確認できているのですが、
部分ビュー内でしか使わないようなJavaScriptをビューの方にまとめられないかと?と思っています。

該当のソースコード

Views/Shared/_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - マイ ASP.NET アプリケーション</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>

<body>
    <div class="container body-content">
        @RenderBody()
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", false)
</body>
</html>

Views/Shared/_TopixView.cshtml

@section scripts
{
    <script type="text/javascript">
        document.getElementById("topixTitle").style.color = "red";
    </script>
}


<h2 id="topixTitle">トピックス</h2>

Views/Home/Index.cshtml

@{
    ViewBag.Title = "Home Page";
}

@section scripts
{
    <script type="text/javascript">
        document.getElementById("title").style.color = "blue";
    </script>
}

<h2 id="title">Home Index</h2>

<div>
    @Html.Partial("_TopixView")
</div>

補足情報(言語/FW/ツール等のバージョンなど)

Windows 10
Visual Studio Professional 2017
ASP.NET MVC 5
Bootstrap 3.3.7
jQuery 3.2.1

追記-1
修正依頼を受けまして出力されたhtmlファイルを追記します。
(見やすいように改行・インデントは変更しています。)

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home Page - マイ ASP.NET アプリケーション</title>
    <link href="/Content/bootstrap.css" rel="stylesheet" />
    <link href="/Content/site.css" rel="stylesheet" />
    <script src="/Scripts/modernizr-2.6.2.js"></script>
</head>

<body>
    <div class="container body-content">
        <h2 id="title">Home Index</h2>
        <div>
            <h2 id="topixTitle">トピックス</h2>
        </div>
    </div>

    <script src="/Scripts/jquery-1.10.2.js"></script>
    <script src="/Scripts/bootstrap.js"></script>
    <script src="/Scripts/respond.js"></script>
    <script type="text/javascript">
        document.getElementById("title").style.color = "blue";
    </script>

</body>
</html>

追記-2
部分ビューは別のページにも配置されるので、
@Html.Partal("_TopixView")の次の行に@section scriptsを書く案は、現実的ではないですね。
いちおう試してみたのですが@section scriptsの分割して書くと
「HttpException」が吐かれるので、一カ所にまとめないと駄目でした。
セクション名を変えれば大丈夫でしたが。

外部ファイルにする案は、
topix.js

document.getElementById("topixTitle").style.color = "red";

_TopixView.cshtml

<h2 id="topixTitle">トピックス</h2>

<script type="text/javascript" src="~/Scripts/topix.js"></script>


上記のようにすると反映されるようになりました。

ただ、sk_3122様が書かれているのですが、投稿したコードのように単純なものではなく
実際のコードはAjaxでJSONデータ受け取ってDOMでゴニャゴニャするつもりなので、
どうなるかを試してみたいと思います。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • lain

    2017/11/24 17:35

    deferを使用する方法を試してみました。jQueryを使用したコードでも動作しました。これは良く使われる方法なのですか?(初めて見た気がするので...)

    キャンセル

  • SurferOnWww

    2017/11/24 17:44

    defer はもともとは IE 専用だったようですが、最近は他のメジャーなブラウザでも使えるようです。

    キャンセル

  • lain

    2017/11/27 09:46

    deferを使用したコードで、いま確認できる環境、Windows/IE11/Edge/Chrome、android/Chrome、iPhone/Chrome/Safariでの(それぞれ最新バージョン)動作は確認できました。どこまで古いOS・ブラウザに対応させるかは別途検討するとして、有益な情報ありがとうございました。

    キャンセル

回答 3

checkベストアンサー

0

(コメント欄にもコードが書けると良いのですけど…)

「jsを読み込んでから<body>内を読みにいくから表示が遅くなる」というのを、
どこかで書かれていたのと、
VSが作成するテンプレートも下に書かれているので、最近はそういうものだという認識でいたのですが。

正直 まんま同じです…
自動生成されたコードがこうなっているからとりあえずこの並びにしておこう、的な…

まあVSの自動生成コードじゃない、一般的な html では
jquery の読み込みを <head> に書いてるケースとかも見るので、
head に持ってって駄目なことはないのではないかと思うのですが…


一応参考までに、
私が実装した際は、部分ビューで使用する外部ファイルの読み込みは
Index.cshtml の @section Scripts {} に書きました。
これなら jquery の後にレンダリングされるので。

もう 「部分Viewの読み込み」 + 「部分View用の外部ファイルの読み込み」 はワンセット、と割り切りました。
(js + css でワンセット、みたいなライブラリもあるし、同じような感じで もうルール化してしまえばそれはそれで良いかなと)

特定の部分View用に読み込む外部ファイルには、一応コメントを付けて後で分かるようにだけしておきました。

Index.cshtml

@section scripts {
<script type="text/javascript" src="../js/my-calendar.js"></script>
<script type="text/javascript" src="../js/hoge-edit.js"></script> <!-- Hoge001用 -->
<script type="text/javascript" src="../js/hoge001.js"></script> <!-- Hoge001用 -->

<script>
  ...
</script>
}

...

@Html.Partial("_Hoge001")

投稿 2017/11/24 18:13

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/24 18:36

    できるだけ、一人の回答者は一つの回答欄を使っていただけないでしょうか(それがTeratail の流儀のようですので)。Teratail は know-how の蓄積も目的としているとのことで、後から検索などでここにたどり着いた人にも読みやすくなるような配慮をいただけると幸いです。

    キャンセル

  • 2017/11/24 18:45

    すみません、そう思ったのですが
    コメント欄だとコードが書けなくて・・・ と思ったのですが、回答欄に追記で書けば良かったですね。(今気が付きました)
    すみません、今度から追記で書くようにします。

    キャンセル

  • 2017/11/27 10:09

    もともとの疑問であった
    「@RenderSection()」「@section sectionName{}」のセットが部分ビューで使用できない事が分かりました。

    そのうえで、どうすれば良いかのご提案いただき、ありがとうございます。

    部分ビューに対応するJavaScriptファイルを作成して、下記の2パターンで実現できました。
    1、部分ビューの中でdeferを使用し定義する。
    2、部分ビューを埋め込むcshtmlの@sectionの中で定義する。

    どちらが良いかは好みの問題になるかと思うので、どうするかはこれから考えてみます。

    ベストアンサーはこちらのほうにしか付けられないので、こちらに付けましたが、
    SurferOnWww様、sk_3122様ありがとうございました。

    キャンセル

0

私も色々調べながら実装しているので全く詳しくはないのですが…
部分Viewは何回も読み込まれるケースを想定しているので、部分View内で @section は使えないよ!ということみたいですね。

でも一回しか読み込まないし、その部分Viewでしか使わないjsをまとめたいよ!と私も思ったので、
私は以下のようにしてみたのですが… どうなんでしょうね。 私も正解が知りたいです・・・


_Hoge001.cshtml (部分View)

...

<script>
var Hoge001Js = {

    // 初期処理
    init: function() {
        var self = this;

        // btn-hello クリック時の処理
        $("#btn-hello").on("click", function() {
            self.sayHello("Yamada");
        });

        // btn-seeyou クリック時の処理
        $("#btn-seeyou").on("click", function() {
            self.saySeeyou("Suzuki");
        });
    },

    // 関数
    sayHello: function(name) {
        alert("Hello, " + name);
    },

    // 関数
    saySeeyou: function(name) {
        alert("See you " + name);
    }

};
</script>

Index.cshtml

...

@section Scripts {
<script>

    $(function() {

        if (window.Hoge001Js) {
            Hoge001Js.init();
        }

    });

</script>
}

部分Viewでは Hoge001Js の定義だけする。
Index で、Hoge001Js が定義されていたら Hoge001Js.init() を呼ぶ、的な

投稿 2017/11/24 12:45

編集 2017/11/24 16:14

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/24 13:50

    外部スクリプトファイルの場合はどのようになりますか?

    キャンセル

  • 2017/11/24 14:14 編集

    部分View固有のスクリプトを外部ファイルに書いた場合、ということでしょうか。

    その場合は Index.cshtml の @section scripts に外部ファイルの読み込みを記述する感じになるかなあと思います。

    -----
    @section scripts {
    <script type="text/javascript" src="../js/hoge001.js"></script>

    <script>
    ...
    </script>
    }
    -----

    ====================

    ↓ _Layout.cshtml の記述
    ----
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", false)
    ----

    上のような感じになってる場合、
    @section scripts {} 内に書かれたものは jquery の後にレンダリングされるのですが、
    多分 部分View内に外部ファイルの読み込みを書くと、jquery の読み込みよりも先に読まれると思います。

    jquery 等を使用していない、標準javascriptのみで書かれたものなら部分View内で読み込んでしまってもよさそうな気はします。
    (試してませんが)

    キャンセル

  • 2017/11/24 15:23

    追記-2の方に外部スクリプトを使用する場合を試してみました。
    今回質問のような単純なJavaScriptの場合はうまくいきました。

    実際はjQueryを使ったりするつもりなので、使ったのを試してみたいと思います。

    キャンセル

0

ちょっとコードが書きたかったのでこっちに書きます。
読み込まれる順番は以下のようになっていると認識しています。

部分View に 「jquery を使用しているスクリプトファイルの読み込み」 を
そのまま書いちゃうと多分まずかろうと思うのは、
@RenderBody() が @Scripts.Render("~/bundles/jquery") よりも前にあるからです。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - マイ ASP.NET アプリケーション</title>
    @Styles.Render("~/Content/css")   @* ★BundleConfig.cs で new StyleBundle("~/Content/css") に指定されているものはここにレンダリングされる *@
    @Scripts.Render("~/bundles/modernizr")
</head>

<body>
    <div class="container body-content">
        @* ★Index.cshtml の内容はここにレンダリングされる、なので部分Viewに書いた内容もここにレンダリングされる *@
        @RenderBody()
    </div>

    @Scripts.Render("~/bundles/jquery")  @* ★jquery のjsはここで読み込まれる *@
    @Scripts.Render("~/bundles/bootstrap")  @* ★bootstrap のjsはここで読み込まれる *@
    @RenderSection("scripts", false)  @* ★section Scripts {} に書かれたものはここにレンダリングされる *@
</body>
</html>

@Scripts.Render() 達を <body> の前に持ってっちゃっても良いものなのかどうかはちょっとわからないです
(´□`)???

投稿 2017/11/24 15:46

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/24 17:26

    こういう風に書いていただくと、理解しやすいです。

    部分ビューの中にjsを書いて、下の@Script.Render達を<head>内に置いて実行すると、
    確かに動作はします。

    最後に書かれているように、jsを前に持っていくのはどうなんでしょうか?
    「jsを読み込んでから<body>内を読みにいくから表示が遅くなる」というのを、
    どこかで書かれていたのと、
    VSが作成するテンプレートも下に書かれているので、最近はそういうものだという認識でいたのですが。

    そういえば、昔は<head>内に書かれていたような...


    stackoverflowで今回の質問と同じ内容(MVC3ですが)を見つけたので読んでいたのですが、
    部分ビューにJS書くのは駄目とか書いてあったりして(英語苦手なので間違えてるかもしれませんが)、
    今回の質問の根底部分が揺らいできています。

    https://stackoverflow.com/questions/7556400/injecting-content-into-specific-sections-from-a-partial-view-asp-net-mvc-3-with

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.35%

関連した質問

同じタグがついた質問を見る

  • ASP.NET

    389questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • MVC

    171questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。