none
ASP.NET MVC5の部分ビュー(PartialView)でJavaScriptを有効にする方法 RRS feed

  • 質問

  • ASP.NET MVC5でマスタ詳細画面を作成していて、

    コントローラーでDBデータ取得し、PartialViewを返して、画面では正しく動いているのですが、

    部分ビューでjavascriptが動かなくて困ってます。

    javascriptの内容は、jqueryで部分ビューを表示する(.loadの部分)と、

    テーブルをクリックすると行の色が変わって、下側のテキストボックスに反映するようにしてます。

    部分ビューを表示する(.loadの部分)は動いているので表示できています。

    PartialView無しでIndex.cshtmlに全部記載していた時はjavascriptは問題なく動いてました。

    javascriptの実行のタイミングなのかとは思いますが。

    どなたかわかるかたいらっしゃいましたらご教授お願いします。

    ■画面

    ■index.cshtml

    @model Test.Models.Member @{ ViewBag.Title = "Member"; } @Styles.Render("~/Content/Site.css") <h2>@ViewBag.Title</h2>

    <!-- PartialViewを表示するエリア -->

    <div id="lists"></div> <div id="edit"></div> @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script> // $(window).on("load", function() { $(document).ready(function () { $("#lists").load("/Member/Lists/"); $("#edit").load("/Member/Edit/"); }); // clickable row $("#myTable").on("click", ".clickable_row", function (event) { $(this).addClass("active").siblings().removeClass("active"); var array = new Array(); for (i = 0; i < $(this).children().length; i++) { var $element = $(this).children().eq(i); if ($element.find("input").is(':checkbox')) { if ($element.find("input").prop("checked")) { array.push(true); } else { array.push(false); } } else { array.push($element.text().trim()); } } var text = array.join(",") console.log($(this).index() + ": " + text); // textbox update $("#Member_Name").val(array[0]); $("#Member_Email").val(array[1]); $("#Member_Birth").val(array[2]); $("#Member_Married").prop("checked", array[3]); $("#Member_Memo").val(array[4]); }); </script> }

    ■Lists.cshtml (コード訂正)

    @model IEnumerable<Test.Models.Member>
    
    @{
        ViewBag.Title = "List";
    }
    
    <h2>List</h2>
    <table class="table" id="myTable">
        <tr>
            <th>氏名</th><th>メールアドレス</th><th>誕生日</th><th>既婚</th><th>備考</th>
        </tr>
        @foreach (var item in Model) {
        <tr>
          <td>@item.Name</td>
          <td>@item.Email</td>
          <td>@item.Birth</td>
          <td>@item.Married</td>
          <td>@item.Memo</td>
        </tr>
      }
    </table>


    ■Edit.cshtml

    @model Test.Models.Member @{   Layout = null; } @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> @Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Birth, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Birth) @Html.ValidationMessageFor(model => model.Birth) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Married, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Married) @Html.ValidationMessageFor(model => model.Married) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Memo, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Memo) @Html.ValidationMessageFor(model => model.Memo) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Edit" class="btn btn-default" /> </div> </div> </div> }

    本来のASP.NET MVCのやりかたではないかもしれませんが、

    部分更新するのに何か他の方法はあるのでしょうか。

    ①現状のままで対処的な方法

    ②ASP.NET MVCでの他の方法、メソッドなど。

    ③パーシャルビューを使わない方法

    ④コントローラーでからJSONデータをViewで受け取って加工して表示


    参考書やネットでは調べているのですが、検討違いな質問があればすみません。






    • 編集済み yuchan01 2019年5月21日 15:34 文章修正
    2019年5月19日 17:09

回答

  • 質問者さんからの反応がなくなってしまいましたが・・・

    上のレスの (3) について、どうしてもパーシャルビューの使用にこだわりたいということであれば、以下を試してみてはいかがですか。

    上に質問者さんがアップされたコードには id="lists" の html 要素は書いてないですが、実際は以下のようにしていると想像しています。

    <div id="lists"></div>
    $("#list").load("/Member/Load/");

    だから、

    > #myTableはlist.cshtmlの中にあるので、javascriptが動きませんでした。
    > 余計なイベントが発生するのは問題
    > テーブルが遅れて表示されるのも問題

    という問題になるのではないかと思います。そうであれば、以下のように変更して試してみてはいかがでしょう?

    <div id="lists">
        @Html.Action("Lists", "Member")
    </div>

    初期画面では @Html.Action("Lists", "Member") により表示され、Ajax ヘルパーで書き換える際は div 要素の中身が置き換わるはずなので、上の問題は全て解決できるのではないかと思われます。お試しください。

    上記では (1) と (2) は解決できませんが、対応するかどうかはご自分で考えて決めてください。

    何にせよ、このスレッドの課題、

    > ASP.NET MVC5の部分ビュー(PartialView)でJavaScriptを有効にする方法

    はすでに解決できたはずですので、いつまでも引っ張らないでクローズしていただければと思います。

    • 編集済み SurferOnWww 2019年5月29日 4:02 訂正: @Scripts.Render("~/bundles/jqueryval") ⇒ $("#list").load("/Member/Load/");
    • 回答としてマーク yuchan01 2019年6月3日 16:30
    2019年5月29日 3:19

すべての返信

  • ビュー index.cshtml のスクリプト、

    > $("#myTable").on("click", ".clickable_row", function (event) {

    で、id が myTable の要素の click 属性にリスナをアタッチして、それによって、

    > テーブルをクリックすると行の色が変わって、下側のテキストボックスに反映するようにしてます。

    ということをしていると想像してます。合ってますか? もし違っていたら、どこがどう違うのか詳しく書いてください。

    その想像が合っているとすると、id が myTable の要素は index.cshtml にもパーシャルビュー Lists.cshtml, Edit.cshtml にも見当たりません。

    それではリスナが動くわけはありませんよね? どこか書いてないところにあるのですか?

    > PartialView無しでIndex.cshtmlに全部記載していた時はjavascriptは問題なく動いてました。

    とのことですから、「全部記載していた」一部をパーシャルビュー Lists.cshtml に移す時に table 要素に id="myTable" を書き忘れた?

    そうだとして、パーシャルビュー Lists.cshtml の table 要素に id="myTable" を追加しても、タイミングの問題でリスナはアタッチできないのでは?

    何故なら index.cshtml のスクリプトが解析される時点ではパーシャルビュー Lists.cshtml はレンダリングされてないからです。


    ビュー index.cshtml からのパーシャルビューの呼び出しをスクリプトで行っているようですが、何か特別な理由があるのでしょうか? 

    そもそも、パーシャルビュー Lists.cshtml は作らないで index.cshtml に埋め込んでしまえばよさそうですが、パーシャルビューにする特別な理由があるのでしょうか?

    特に理由はないということでしたら、普通の ASP.NET MVC のやり方ではないので、そのあたりから全面的に見直した方がよさそうだと思います。

    • 編集済み SurferOnWww 2019年5月20日 1:24 誤字訂正
    2019年5月20日 1:10
  • コメントありがとうございます。
    コメントいただいた認識で合ってます。
    すみません、Lists.cshtml のtableにid=myTableを書き忘れてましたが、実際は記述していまして、 おっしゃられるとおり記載したところで、タイミングの問題で実行ができないことと、 Lists.cshtmlをパーシャルビューにしている理由は、データ更新時にページ全体を再読み込みしたくないからです。

    テキストボックス入力後に更新実行して→テーブル画面の部分更新をしたいです。
    ListsはIndexが終わってから読み込まれるんですね。

    javascriptを実行するのに、もしパーシャルビュー以外の方法があれば良いのですが。


    • 編集済み yuchan01 2019年5月20日 4:14
    2019年5月20日 4:10
  • > ListsはIndexが終わってから読み込まれるんですね。

    質問に書かれたコードでは、パーシャルビューの部分がレンダリングされる前(table id="myTable" などがまだ存在しない時)に、

    $("#myTable").on("click", ".clickable_row", function (event) { ... }); 

    が読み込まれて解析され、その後

    $(document).ready(function () { ... });

    でパーシャルビューがレンダリングされる(その時初めて table 要素が存在する)という順序になるはずです。

    存在しない要素のイベントにはリスナはアタッチできないということで、スクリプトが動かないということになっていると思います。

    > Lists.cshtmlをパーシャルビューにしている理由は、データ更新時にページ全体を再読み込みしたくないからです。 

    そこが理解できませんし、迷走しているような気がします・・・が、とりあえず、パーシャルビューを使うという今のコードを大幅に変えないという条件で考えると、対症療法的な気がしますが、以下を試してみてはいかがでしょう。

    table 要素の onclick 属性にリスナをアタッチできるようにするには、

    $("#myTable").on("click", ".clickable_row", function (event) { ... }); 

    の前にパーシャルビューの部分が完全にレンダリングされた形の html ソースをブラウザが受信している必要があるはずです。

    パーシャルビューはコントローラー MemberController のアクションメソッド Lists, Edit 経由で呼び出すようにしていると思いますが、であれば

    <div id="lists"></div>
    <div id="edit"></div>

    に代えて、

    @Html.Action("Lists", "Member")
    @Html.Action("Edit", "Member")

    としてみてはいかがでしょう?

    $(document).ready(function () { ... }); は不要なのでコメントアウトして試してみてください。

    それでうまくいかない、期待と違うという場合は、どこがどうダメなのか詳しく書いてください。


    • 編集済み SurferOnWww 2019年5月21日 0:43 誤記訂正: oncick ⇒ onclick
    2019年5月20日 5:24
  • ご返信遅くなりすみません。検証していました。

    >パーシャルビューがレンダリングされる(その時初めて table 要素が存在する)という順序になるはずです。
    >存在しない要素のイベントにはリスナはアタッチできないということで、スクリプトが動かないということになっていると思います。

    レンダリングの順序で、イベントとリスナの問題があり実行できない場合があるのですね。

    また、コードを修正し、@Html.Action("Lists", "Member")を追加することで、javascriptを実行することができましたが、

    @Html.Actionでは div id="lists"のようにidを付加できないので、


    例えば検索ボタン(検索用テキストボックス一旦は省略)を追加して、部分ビューを更新するような処理が必要なのですが、

    本来の目的をすることができなく困ってます。

    画面イメージを修正しました。


    ■ コードを修正しました。テーブルのクリックイベントは動きましたが、divタグのidがないのでSearchボタンは実行できないです。

    @model Test.Models.Member
    
    @{
        ViewBag.Title = "Member";
    }
    
    @ViewBag.Title
    
    
    
    <button type="button" class="btn btn-search">Search</button>
    
    @Html.Action("Lists", "Member")
    
    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()
        
        
    
            @Html.ValidationSummary(true)
    
            
    
                @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
                
    
                    @Html.EditorFor(model => model.Name)
                    @Html.ValidationMessageFor(model => model.Name)
                
    
            
    
    
            
    
                @Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })
                
    
                    @Html.EditorFor(model => model.Email)
                    @Html.ValidationMessageFor(model => model.Email)
                
    
            
    
    
            
    
                @Html.LabelFor(model => model.Birth, new { @class = "control-label col-md-2" })
                
    
                    @Html.EditorFor(model => model.Birth)
                    @Html.ValidationMessageFor(model => model.Birth)
                
    
            
    
    
            
    
                @Html.LabelFor(model => model.Married, new { @class = "control-label col-md-2" })
                
    
                    @Html.EditorFor(model => model.Married)
                    @Html.ValidationMessageFor(model => model.Married)
                
    
            
    
    
            
    
                @Html.LabelFor(model => model.Memo, new { @class = "control-label col-md-2" })
                
    
                    @Html.EditorFor(model => model.Memo)
                    @Html.ValidationMessageFor(model => model.Memo)
                
    
            
    
    
            
    
                
    
                    <input type="submit" value="Create" class="btn btn-default" />
                    <input type="submit" value="Edit" class="btn btn-default" />
                    <input type="submit" value="Delete" class="btn btn-default" />
                
    
            
    
        
    
    }
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
        <script>
            $("#lists").load("/Member/Lists/");
    
            // clickable row
            $("#myTable").on("click", ".clickable_row", function (event) {
                $(this).addClass("active").siblings().removeClass("active");
    
                var array = new Array();
                for (i = 0; i < $(this).children().length; i++) {
                    var $element = $(this).children().eq(i);
                    if ($element.find("input").is(':checkbox')) {
                        if ($element.find("input").prop("checked")) {
                            array.push(true);
                        } else {
                            array.push(false);
                        }
                    } else {
                        array.push($element.text().trim());
                    }
                }
    
                var text = array.join(",")
                console.log($(this).index() + ": " + text);
    
                // textbox update
                $("#Name").val(array[0]);
                $("#Email").val(array[1]);
                $("#Birth").val(array[2]);
                $("#Married").prop("checked", array[3]);
                $("#Memo").val(array[4]);
            });
    
            // Search
            $(".btn-search").click(function (e) {
                $("#lists").load("/Member/Lists/");
            });
        </script>
    }


    普通の ASP.NET MVC のやり方ではないかもしれませんが、


    部分ビューを更新するのに何か他の方法はあるのでしょうか?例えば

    ①現状のままで対処的な方法、ページまたはjavascript修正

    ②ASP.NET MVCでほかになにか使えそうなパターン、メソッドなど

    ③コントローラーでパーシャルビューを使わないで部分更新する方法

    ④コントローラーでjsonデータをViewに返してもらい加工して表示など

    参考書やネットで知らべてはいるのですが、私の知識も乏しく検討違いな質問が含んでいればすみませんが。









    • 編集済み yuchan01 2019年5月26日 13:55 HTMLコードフォーマットの修正
    2019年5月21日 15:19
  • > @Html.Actionでは div id="lists"のようにidを付加できないので、例えば検索ボタン(検索用テキストボックス一旦は省略)を追加して、部分ビューを更新するような処理が必要なのですが、本来の目的をすることができなく困ってます。

    どうして「div id="lists"のようにidを付加」すると[検索ボタン]が働くのか全く不明です。

    [検索ボタン]は button type="button" のようですが、それだとクリックしても何も起こらないはず。

    検索はサーバー側で行ってその結果を返して表示するのでしょうから、クリックしても何も起こらないのでは何ともならないのでは?

    実は type="button" ではなくて type="submit" だとか?

    それとも、button type="button" 要素の onclick 属性にリスナをアタッチしてそれで処理している? でも質問者さんがアップしたコードにはそういうスクリプトは見当たらないし・・・

    そもそも、なぜ一覧をパーシャルビュー Lists.cshtml で表示する必要があるのですか? index.cshtml に埋め込んだ方が処置はよほど簡単になるはず。

    先の質問者さんのレスで、

    > Lists.cshtmlをパーシャルビューにしている理由は、データ更新時にページ全体を再読み込みしたくないからです。

    とありましたが、パーシャルビューを使ってもそれだけで上の目的が果たせるということはなく、Ajax ヘルパーと組み合わせないとパーシャルビューの部分のみ再描画ということができないはずです。

    でも、アップされているコードには Ajax ヘルパーは見当たりません。質問にアップしたコードには書いてないけど実際にはどこかにある? 

    上の[検索ボタン]の件もそうですが、質問に書いてないことがいろいろあるのでは?

    そうでなければ迷走しているとしか思えないのですが。


    基本的にやりたいことは、SQL Server などの DB のテーブルからレコード一覧を取得して表示し、レコードの追加、削除、変更を行いたいということだと理解しています。

    既存のデータベースから Entity Data Model (EDM) を作り、スキャフォールディング機能を使って Create, Read, Update, Delete (CRUD) 操作を行うためのMVC アプリを作ったことはありますか。

    もしやったことがないのであれば、一度作ってみてください。手順は下記の記事が参考になると思います。

    スキャフォールディング機能
    http://surferonwww.info/BlogEngine/post/2017/07/23/creating-controller-and-view-in-mvc-using-scaffolding-function.aspx

    それにフィルタリング機能を組み込むのは以下のチュートリアルのようにします。

    Tutorial: Add sorting, filtering, and paging with the Entity Framework in an ASP.NET MVC application
    https://docs.microsoft.com/ja-jp/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application

    それをベースに、質問者さんの目的に沿ってどのように手を加えるかを考えることをお勧めします。

    • 回答としてマーク yuchan01 2019年5月26日 13:51
    • 回答としてマークされていない yuchan01 2019年5月27日 3:21
    2019年5月22日 2:34
  • 最初の質問を修正・変更したようですが、一旦レスが付いたらそれは NG です。ここを訪れる閲覧者(特に後日検索などにヒットしてここを見る人)は上から順に読んでいきますから、後の方のレスと話の辻褄が合わなくなって混乱を招きます。止めましょう。(変更するなら、変更したこと、その日時などを追記して、後でここを訪れた人にも経緯が分かるようにしてください)
    2019年5月22日 3:02
  • お返事遅くなりすみません。検証していました。

    もともと記載していたコードはスキャフォールディング機能にてモデルから作成したコントローラーとビューを加工していたものです。

    Index, Create, Edit, Delete, Detailにページが分かれているのでは使いにくいので、

    スキャフォールディング機能にて作成してから、コードを流用して1ページ(部分ビュー有り)に集約したいためです。


    >Ajax ヘルパーと組み合わせないとパーシャルビューの部分のみ再描画ということができないはずです。

    これについては私のほうで理解してませんでした。



    いろいろとヒントを頂きましたので、一旦希望の動作をすることができました。

    マルチsubmitも追加してます。

    以下、イメージとコードを掲載します。 Create、Edit、Deleteは検証していないのでコントローラーの実行中エラーすると思います。※修正しましたら再度掲載の予定。

    ただしリスト部の表示が遅れて表示してしまうのは改善したいですが。


    そもそも、なぜ一覧をパーシャルビュー Lists.cshtml で表示する必要があるのですか? index.cshtml に埋め込んだ方が処置はよほど簡単になるはず。

    このことについてはわかりませんでしたので、どのような方法を取ればよいかご教授いただきたく。



    ■完成イメージ

    ■Index.cshtml

    @model Test.Models.Member
    
    @{
        ViewBag.Title = "Member";
    }
    
    

    @ViewBag.Title

    @using (Ajax.BeginForm("Select", "Member", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "list" })) { <input type="submit" value="Search" class="btn btn-search" /> }
    @using (Ajax.BeginForm("Action", "Member", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "list" })) { @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
    @Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name)
    @Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })
    @Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email)
    @Html.LabelFor(model => model.Birth, new { @class = "control-label col-md-2" })
    @Html.EditorFor(model => model.Birth) @Html.ValidationMessageFor(model => model.Birth)
    @Html.LabelFor(model => model.Married, new { @class = "control-label col-md-2" })
    @Html.EditorFor(model => model.Married) @Html.ValidationMessageFor(model => model.Married)
    @Html.LabelFor(model => model.Memo, new { @class = "control-label col-md-2" })
    @Html.EditorFor(model => model.Memo) @Html.ValidationMessageFor(model => model.Memo)
    <input type="submit" value="Create" name="Create" class="btn btn-default" /> <input type="submit" value="Edit" name="Edit" class="btn btn-default" /> <input type="submit" value="Delete" name="Delete" class="btn btn-default" />
    } @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script> $("#list").load("/Member/Load/"); $("body").on("click", ".clickable_row", function (event) { $(this).addClass("active").siblings().removeClass("active"); var array = new Array(); for (i = 0; i < $(this).children().length; i++) { var $element = $(this).children().eq(i); if ($element.find("input").is(':checkbox')) { if ($element.find("input").prop("checked")) { array.push(true); } else { array.push(false); } } else { array.push($element.text().trim()); } } $("#Name").val(array[0]); $("#Email").val(array[1]); $("#Birth").val(array[2]); $("#Married").prop("checked", array[3]); $("#Memo").val(array[4]); var text = array.join(",") console.log($(this).index() + ": " + text); }); </script> }


    ■MemberController.cs

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Entity;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Mvc;
    using Test.Models;
    
    namespace Test.Controllers {
        public class MemberController : Controller {
            private MvcBasicContext db = new MvcBasicContext();
    
            // GET: /Member/
            public ActionResult Index() {
                return View();
            }
    
            public ActionResult Load() {
                if (!Request.IsAjaxRequest()) return new EmptyResult();
                return PartialView("list", db.Members.ToList());
            }
    
            public ActionResult Select() {
                if (!Request.IsAjaxRequest()) return new EmptyResult();
                return PartialView("list", db.Members.ToList());
            }
    
            // POST: /Member/Create
            // 過多ポスティング攻撃を防止するには、バインド先とする特定のプロパティを有効にしてください。
            // 詳細については、http://go.microsoft.com/fwlink/?LinkId=317598 を参照してください。
            [HttpPost]
            [HttpParamAction]
            [ValidateAntiForgeryToken]
            public ActionResult Create([Bind(Include = "Id,Name,Email,Birth,Married,Memo")] Member member) {
                if (ModelState.IsValid) {
                    db.Members.Add(member);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
    
                // return View(member);
                return PartialView("list", db.Members.ToList());
            }
    
            // POST: /Member/Edit/5
            // 過多ポスティング攻撃を防止するには、バインド先とする特定のプロパティを有効にしてください。
            // 詳細については、http://go.microsoft.com/fwlink/?LinkId=317598 を参照してください。
            [HttpPost]
            [HttpParamAction]
            [ValidateAntiForgeryToken]
            public ActionResult Edit([Bind(Include = "Id,Name,Email,Birth,Married,Memo")] Member member) {
                if (ModelState.IsValid) {
                    db.Entry(member).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                // return View(member);
                return PartialView("list", db.Members.ToList());
            }
    
            // POST: /Member/Delete/5
            [HttpPost, ActionName("Delete")]
            [HttpParamAction]
            [ValidateAntiForgeryToken]
            public ActionResult DeleteConfirmed(int id) {
                Member member = db.Members.Find(id);
                db.Members.Remove(member);
                db.SaveChanges();
                // return RedirectToAction("Index");
                return PartialView("list", db.Members.ToList());
            }
    
            protected override void Dispose(bool disposing) {
                if (disposing) {
                    db.Dispose();
                }
                base.Dispose(disposing);
            }
        }
    }


    ■Member.cs

    using System;
    using System.ComponentModel;
    
    namespace Test.Models {
        public class Member {
            public int Id { get; set; }
    
            [DisplayName("氏名")]
            public string Name { get; set; }
    
            [DisplayName("メールアドレス")]
            public string Email { get; set; }
    
            [DisplayName("生年月日")]
            public DateTime Birth { get; set; }
    
            [DisplayName("既婚")]
            public bool Married { get; set; }
    
            [DisplayName("自己紹介")]
            public string Memo { get; set; }
        }
    }

    また、以下は Request.IsAjaxRequest()が動かなかったので追加しました。

    ■Nugetパッケージ追加

    PM > Install-Package Microsoft.jQuery.Unobtrusive.Validation -Version 3.2.11

    ■ BundleConfig.csに追加

    // Ajax通信用に追加
    bundles.Add(new ScriptBundle("~/bundles/jqueryajax").Include(
                "~/Scripts/jquery.unobtrusive-ajax*"));

    ■_Layout.cshtmlのRenderSectionの少し上あたりに追加

    @Scripts.Render("~/bundles/jqueryajax")



    • 回答としてマーク yuchan01 2019年5月26日 13:51
    • 編集済み yuchan01 2019年5月26日 23:12
    • 回答としてマークされていない yuchan01 2019年5月27日 3:21
    2019年5月26日 13:37
  • 文章のおかしな部分、コードが崩れているのを修正しようとしてましたが、コードの崩れている部分がよくわかりませんでした、

    他何か等変わっているようでしたらすみませんが気を付けます。

    2019年5月26日 13:51
  • 完全ではない自分のコードをアップして「回答としてマーク」を付けるのはいかがなものかと思うのですが・・・

    UpdateTargetId = "list" の html 要素はどこにあるのでしょう。Index.cshtml の中にはなさそうですが? その他、Create、Edit、Delete も含めて期待通り動くところまでは検証されてないのですよね。

    あと、私のレスにも「回答としてマーク」を付けていますが、それは回答にはなっていないので外しておくようお願いします。

    タイトルの、

    > ASP.NET MVC5の部分ビュー(PartialView)でJavaScriptを有効にする方法

    に戻ってレスします。その他の話はこのスレッドでは止めておいた方がよさそうです。

    パーシャルビューを使っても JavaScript が動くようにできたということのようですが、かなり微妙な感じがします。それは何かと言うと:

    (1) Ajax ヘルパーを使って、ボタンクリックでパーシャルビューの中身のみ書き換えるということをしているようですが、その際 JavaScript は書き換えてないようなので、パーシャルビューの内容と整合が取れなくなることがあるのでは? (今回のコードではたまたま整合がとれているのかもしれませんが)

    (2) $("#Name").val(array[0]); は @Html.EditorFor(model => model.Name) がレンダリングする html 要素の id が Name になると考えてそう設定したと思いますが、必ずそうなるという保証はない(少なくとも自分は Microsoft の公式文書では見たことがないです)

    (3) $("body").on("click", ".clickable_row", function (event) { ... }); というところ、なぜ #myTable を止めて body にしたのか分かりませんが、table 以外の他の要素をクリックしたときもバブリングで body に上がってきてしまう。(余計なクリックイベントが捕捉されてしまう)

    そのあたりを考えた方がよさそうな気がします。


    • 編集済み SurferOnWww 2019年5月27日 2:53 訂正&追記
    2019年5月27日 2:48
  • 「回答としてマーク」を解除させて頂きました。
    どんなルールで書き込みするか、すべて把握できてませんので、間違い等はご了承くださいとするのは、おかしいかもしれませんが、
    私も気をつけます。

    create, edit, deleteの検証と、ご指摘の、(1)(2)(3)の部分についてしばらく検証します。

    (1)については、list.cshtmlにはjavascriptを書いてませんが、それとは違うことでしょうか?

    (2)は、id=nameになりますので、異なることがあれば変更します。


    (3)の#myTableはlist.cshtmlの中にあるので、javascriptが動きませんでした。
    余計なイベントが発生するのは問題なので、他の方法を考えたいと思います。
    部分ビューで、テーブルが遅れて表示されるのも問題ではありますが。
    2019年5月27日 3:43
  • > 「回答としてマーク」を解除させて頂きました。どんなルールで書き込みするか、すべて把握できてませんので、

    特に後から検索などでこのスレッドを訪れた人は、「回答としてマーク」を問題解決の回答だと思って注目するはずです。なので、回答になってないレスにマークを付けるのは NG ではないでしょうか?

    > create, edit, deleteの検証と、ご指摘の、(1)(2)(3)の部分についてしばらく検証します。

    create, edit, delete の話はこのスレッドの本題である、

    > ASP.NET MVC5の部分ビュー(PartialView)でJavaScriptを有効にする方法

    とは別の問題なので、このスレッドで話をすると発散しそうです。本題が解決した後、質問などがあれば、新たに別のスレッドを立てて質問するようにしてください。

    > (1)については、list.cshtmlにはjavascriptを書いてませんが、それとは違うことでしょうか? 

    JavaScript は部分ビューの DOM を操作するものですが、部分ビューを書き換えて DOM の構成内容が異なってくるケースがあるとすると、それに合わせて JavaScript は書き換えることはしないわけですから、整合がとれなくなる可能性があるということです。

    > (2)は、id=nameになりますので、異なることがあれば変更します。

    Microsoft の公式ドキュメントなどで必ずそうなるという保証がない限り、今回たまたまそういう結果なっただけと考えるのが正解だと思います。(知らないうちに変わるかもしれないと考えるべきでは?)

    MVC4 以降、HTML ヘルパーに IdFor というのがあるので、それを使うことをお勧めします。

    > (3)の#myTableはlist.cshtmlの中にあるので、javascriptが動きませんでした。

    前にも書きましたが、パーシャルビューを使うのは考え直した方が正解だと思いますよ。

    検索ボタンクリックで、Ajax ヘルパーを使ってパーシャルビューの部分のみ書き換えたいのだと思いますが、それを諦めるということになりますけど。

    客の強い要望とかがあるなら話は別ですが、そうでなければ、部分更新できるというメリットと実装の複雑さ(=開発工数と保守工数の増大、質問者さんの力量の問題)によるデメリットを天秤にかけて考えてみてはいかがでしょう。
    2019年5月27日 5:49
  • 質問者さんからの反応がなくなってしまいましたが・・・

    上のレスの (3) について、どうしてもパーシャルビューの使用にこだわりたいということであれば、以下を試してみてはいかがですか。

    上に質問者さんがアップされたコードには id="lists" の html 要素は書いてないですが、実際は以下のようにしていると想像しています。

    <div id="lists"></div>
    $("#list").load("/Member/Load/");

    だから、

    > #myTableはlist.cshtmlの中にあるので、javascriptが動きませんでした。
    > 余計なイベントが発生するのは問題
    > テーブルが遅れて表示されるのも問題

    という問題になるのではないかと思います。そうであれば、以下のように変更して試してみてはいかがでしょう?

    <div id="lists">
        @Html.Action("Lists", "Member")
    </div>

    初期画面では @Html.Action("Lists", "Member") により表示され、Ajax ヘルパーで書き換える際は div 要素の中身が置き換わるはずなので、上の問題は全て解決できるのではないかと思われます。お試しください。

    上記では (1) と (2) は解決できませんが、対応するかどうかはご自分で考えて決めてください。

    何にせよ、このスレッドの課題、

    > ASP.NET MVC5の部分ビュー(PartialView)でJavaScriptを有効にする方法

    はすでに解決できたはずですので、いつまでも引っ張らないでクローズしていただければと思います。

    • 編集済み SurferOnWww 2019年5月29日 4:02 訂正: @Scripts.Render("~/bundles/jqueryval") ⇒ $("#list").load("/Member/Load/");
    • 回答としてマーク yuchan01 2019年6月3日 16:30
    2019年5月29日 3:19
  • お返事遅くなりすみません。検証をしてましたが、まだ不完全ですが、一通り実行できるようになりました。


    教えていただいた @Html.Action("Lists", "Member") でテーブルが遅れて表示されるのは解決できました。

    Create、Edit、Deleteも実行できるようになりましたが、エラー処理など細かな部分ができていないので、

    不完全なコードを掲載するのもよくないかと思いましたので、コードは省略しますが。


    (2)のIdFor については活用したいと思います。


    また、パーシャルビューを使わない方法も考えたいと思います。

    JSONデータからhtmlのtable構築をするか、RenderBodyごと更新ぐらいしか思いつきませんが。

    これで一旦締め切らせていただきたいと思います。ありがとうございました。

    また似たようなご質問をさせて頂くかもかもしれませんが。


    • 編集済み yuchan01 2019年6月3日 16:29
    2019年6月3日 16:28