locked
Displaying Partial View to show Table After Dropdown Change RRS feed

  • Question

  • User-2147270405 posted

    I've read several posts here providing various approaches to various similar scenarios, but I'm still a bit confused about the best approach to this scenario.

    I have a single dropdown where, after an item is selected, I want to use a Partial View containing a table to display several child rows related to the item selected.  I also want to periodically update the table to show the updated status of each child row in the table. (Each row represents a task to be done, which I am running as Async Tasks)

    So, what I'm looking to do is display the Partial View from javascript onchange, and also to display it at intervals as the Tasks run.  The question is: What is the best way to both display the partial view from the onchange AND refresh it at intervals. 

    My primary question is that since I can't just "insert" the partial into the page without refreshing the whole page (unless I use javascript to insert it into the DOM), I'm looking for examples (or guidance) on how to best do those 2 things in javascript. Unless I'm wrong and I CAN simply refresh a partial via the MVC logic itself.

    Like I said, I've looked at tons of posts here and SO, but they all leave me confused. They either seem to show simple dom updates without complex html data, or else seem to involve forms with logic that seems wrong for what I'm trying.

    Any help to "unconfuse" me would be greatly appreciated.

    Wednesday, May 19, 2021 11:00 PM

Answers

  • User1686398519 posted

    Hi bregia, 

    display the Partial View from javascript onchange, and also to display it at intervals as the Tasks run

    Do you mean you want to update the partial view every once in a while?

    • You can use setInterval() method calls a function at specified intervals (in milliseconds)

    My primary question is that since I can't just "insert" the partial into the page without refreshing the whole page

    • You can use ajax to achieve your needs.

    I wrote an example, you can refer to it.

    • I wrote some code comments to help you understand the demo I wrote.

    Model

        public class User
        {
            public int UserId { get; set; }
            public string UserName { get; set; }
            public int RoleId { get; set; }
        }
        public class Role
        {
            public int RoleId { get; set; }
            public string RoleName { get; set; }
        }

    Controller

        public class TestPartialViewController : Controller
        {
            public DailyMVCDemoContext db = new DailyMVCDemoContext();
            public ActionResult Index()
            {
                //get all roles that need to populate the drop-down list
                ViewBag.Roles = new SelectList(db.Roles, nameof(Role.RoleId), nameof(Role.RoleName));
                return View();
            }
            public ActionResult getdata(int RoleId)
            {
                //get all users according to the RoleId
                var userlist = db.Users.Where(m => m.RoleId == RoleId).ToList();
                //return to specified partialview named _partialViewTable with the data:userlist
                return View("_partialViewTable",userlist);
            }
        }

    Index View

    <div class="form-group">
        @Html.DropDownList("Role", ViewBag.Roles as SelectList)
    </div>
    <div class="form-group" id="showdata"></div>
    @section scripts{
        <script>
            //call settabledata() every 1 seconds (1000 milliseconds)
            setInterval(function () { settabledata(); }, 1000);
            $("body").on("change", "#Role", function () {
                settabledata();//call settabledata()
            });
            //request getdata method get the rendered html string of partial view  and put them in div
            function settabledata() {
                $.ajax({
                    url: "@Url.Action("getdata", "TestPartialView")",
                    data: { "RoleId": $("#Role").val() },
                    success: function (data) {
                        $("#showdata").html(data);
                        console.log("getdata");
                    }
                });
            }
        </script>
    }

    _partialViewTable partial view

    @model IEnumerable<DailyMVCDemo.Models.User>
    <table class="tabel table-striped">
        <tr>
            <td>UserId</td>
            <td>UserName</td>
            <td>RoleId</td>
        </tr>
        @foreach (var item in Model)
        {
            <tr>
                <td>@item.UserId</td>
                <td>@item.UserName</td>
                <td>@item.RoleId</td>
            </tr>
        }
    </table>

    Here is the result. 

    Best Regards,

    YihuiSun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, May 20, 2021 6:38 AM

All replies

  • User1686398519 posted

    Hi bregia, 

    display the Partial View from javascript onchange, and also to display it at intervals as the Tasks run

    Do you mean you want to update the partial view every once in a while?

    • You can use setInterval() method calls a function at specified intervals (in milliseconds)

    My primary question is that since I can't just "insert" the partial into the page without refreshing the whole page

    • You can use ajax to achieve your needs.

    I wrote an example, you can refer to it.

    • I wrote some code comments to help you understand the demo I wrote.

    Model

        public class User
        {
            public int UserId { get; set; }
            public string UserName { get; set; }
            public int RoleId { get; set; }
        }
        public class Role
        {
            public int RoleId { get; set; }
            public string RoleName { get; set; }
        }

    Controller

        public class TestPartialViewController : Controller
        {
            public DailyMVCDemoContext db = new DailyMVCDemoContext();
            public ActionResult Index()
            {
                //get all roles that need to populate the drop-down list
                ViewBag.Roles = new SelectList(db.Roles, nameof(Role.RoleId), nameof(Role.RoleName));
                return View();
            }
            public ActionResult getdata(int RoleId)
            {
                //get all users according to the RoleId
                var userlist = db.Users.Where(m => m.RoleId == RoleId).ToList();
                //return to specified partialview named _partialViewTable with the data:userlist
                return View("_partialViewTable",userlist);
            }
        }

    Index View

    <div class="form-group">
        @Html.DropDownList("Role", ViewBag.Roles as SelectList)
    </div>
    <div class="form-group" id="showdata"></div>
    @section scripts{
        <script>
            //call settabledata() every 1 seconds (1000 milliseconds)
            setInterval(function () { settabledata(); }, 1000);
            $("body").on("change", "#Role", function () {
                settabledata();//call settabledata()
            });
            //request getdata method get the rendered html string of partial view  and put them in div
            function settabledata() {
                $.ajax({
                    url: "@Url.Action("getdata", "TestPartialView")",
                    data: { "RoleId": $("#Role").val() },
                    success: function (data) {
                        $("#showdata").html(data);
                        console.log("getdata");
                    }
                });
            }
        </script>
    }

    _partialViewTable partial view

    @model IEnumerable<DailyMVCDemo.Models.User>
    <table class="tabel table-striped">
        <tr>
            <td>UserId</td>
            <td>UserName</td>
            <td>RoleId</td>
        </tr>
        @foreach (var item in Model)
        {
            <tr>
                <td>@item.UserId</td>
                <td>@item.UserName</td>
                <td>@item.RoleId</td>
            </tr>
        }
    </table>

    Here is the result. 

    Best Regards,

    YihuiSun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, May 20, 2021 6:38 AM
  • User-2147270405 posted

    Yes, the 'setinterval()' approach solves that need - thanks for confirming that approach.

    As for your solution, it looks very good, but when I use the logic with MINOR edits to use my data and my controller & dropdown settings, I get a 500 on the ajax call. Working right now to debug that, but I've confirmed using 'alert(x)' debugging that my url data is correct.   I'm using local IIS for this, so I'm working to diagnose that.  

    This works to confirm the controller/action data works:

                $('#DropdownDiv').on('change', '.dropdown', function () {
    
                    //alert("Hello");
                    var url = "/Home/Test";
                    var name = $('#JobBatchList_BatchListItems').val();
                        $.get(url, { BatchID: name }, function (data) {
                            alert(data);
                        });
                });
    

    While this version of yours throws the 500:

                function settabledata() {
                    $.ajax({
                        url: "@Url.Action("Test", "Home")",
                        data: { "BatchId": $(".dropdown").val() },
                        success: function (data) {
                            alert(data);
                        //    $("#_jobsTable").html(data);
                        //    console.log("Test2");
                        },
                        error: function(xhr){
                            alert("An error occured: " + xhr.status + " " + xhr.statusText);
                        }
                    });
                }
    



    Thursday, May 20, 2021 2:28 PM
  • User-2147270405 posted

    Update: I was able to resolve to 500 error using the 'get' method - it was related to using the wrong return signature from the Controller.  But I'm still getting that error using the @UrlAction approach.

    So, this ALMOST works right now, except for a styling error:

               $('#DropdownDiv').on('change', '.dropdown', function () {
    
                    //alert("Hello");
                    var url = "/Home/Test2";
                    var name = $('#JobBatchList_BatchListItems').val();
                        $.get(url, { BatchID: name }, function (data) {
                            //alert(data);
                            $('#_jobsTable').html(data);
                        });
    

    Using this as the Controller:

    public IActionResult Test2(string BatchID)
            {
                mvm.JobBatch = new JobBatchViewModel(BatchID);
    
                return PartialView("Jobs", mvm.JobBatch);
            }

    Unfortunately, I'm seeing a VERY weird behavior that I THINK is probably related to the way I'm updating the DOM. 

    But, what I see is the 'view page source' from before AND after the table refreshes is IDENTICAL. In other words, the reload of the partial IS shown on the screen, but doesn't seem to show up in the page source, which I've NEVER seen before. That is keeping me from identifying what is different about the styling.  Thoughts?

    Thursday, May 20, 2021 4:42 PM
  • User-2147270405 posted

    Update:  I switched over to the Ajax solution you suggested, as that gave me error handling. I've marked your post as the answer.  Here's my script:

                    $.ajax({
                        url: '@Url.Action("Test2", "Home")',
                        type: 'GET',
                        data: { "BatchID": $('#JobBatchList_BatchListItems').val()},
                        dataType: 'html',
                        success: function (result) {
                            $('#_jobsTable').html(result);
                        },
                        error: function (result) {
                            $('#_jobsTable').html("An error occured: " + result.status + " " + result.statusText);
                        }
    
                    })

    Thursday, May 20, 2021 9:29 PM
  • User1686398519 posted

    Hi bregia, 

    as that gave me error handling.

    Can you tell me the specific error message you are appearing?

    Alternatively, you can also F12 to check network activity in the browser.

    Best Regards,

    YihuiSun

    Friday, May 21, 2021 6:28 AM
  • User-2147270405 posted

    Sorry, I didn't dig deeper into the error except to notice that it was a 500 due to me returing the wrong thing from the controller action. So nothing was wrong with the sample sode.

    I did change from a POST to a GET, as all I was doing was sending an ID and getting back a populated table.  So, your sample was basically working fine, and I just added a few adjustments for my use case.

    Friday, May 21, 2021 11:46 AM