Refresh ViewComponent in ASP.Net Core MVC View
Asked Answered
D

1

8

I have a view component, EventsViewComponent, which is loaded in my Events view index.cshtml using the following lines of code:

<div id="events">
    @await Component.InvokeAsync("Events", new { showPrevious = Model.ShowPrevious, showUpcoming = Model.ShowUpcoming })
</div>

I have two checkboxes added like this:

@Html.CheckBoxFor(m => m.ShowPrevious, new { id = "cbShowPrevious", onchange = "ReloadEvents()" })
@Html.CheckBoxFor(m => m.ShowUpcoming, new { id = "cbShowUpcoming", onchange = "ReloadEvents()" })

ReloadEvents() refers to a Javascript function in which I was hoping to refresh the EventsViewComponent with an Ajax call something like:

function ReloadEvents() {
    $.ajax({
        url: '@Url.Action("ReloadEvents", "Events")',
        data: {
            showPrevious: document.getElementById("cbShowPrevious").checked,
            showUpcoming: document.getElementById("cbShowUpcoming").checked
        },
        success: DoThis()
    })
}

function DoThis() {
    const eventsDiv = document.getElementById('events');
    eventsDic.innerHTML = //HTML from EventsViewComponent
}

But I don't seem to be able to get the HTML from the EventsViewComponent.

I have written the Default.cshtml for EventsViewComponent like this:

@{
    List<Event> events = ViewData["Events"] as List<Event>;
    if (events.Count > 0)
    {
        <table>
            //event data from the model
        </table>
    }
}

The InvokeAsync method in EventsViewComponent is being hit, as is the ReloadEvents method in EventsController but I'm obviously misunderstanding something as I don't seem to be able to update the EventsViewComponent.

Please could someone advise if this is possible and how to go about achieveing it?

Dismal answered 9/3, 2020 at 20:51 Comment(0)
R
16

To get the HTML from the EventsViewComponent,you need to change like below:

success: function (data) {
        $("#events").html(data);
}

Here is a whole working demo like below:

1.Model:

public class Event
{
    public bool ShowPrevious { get; set; }
    public bool ShowUpcoming { get; set; }
    public string Data { get; set; }
}

2.ViewComponent:

public class EventsViewComponent : ViewComponent
{
    List<Event> data = new List<Event>() {
        new Event(){ ShowPrevious=true,ShowUpcoming=false,Data="aaa"},
        new Event(){ ShowPrevious=false,ShowUpcoming=true,Data="bbb"},
        new Event(){ ShowPrevious=false,ShowUpcoming=true,Data="ccc"},
    };
    public IViewComponentResult Invoke(bool showPrevious,bool showUpcoming)
    {
        if (showPrevious == true && showUpcoming == true)
        {
            ViewData["Events"] = data;
        }
        else if (showPrevious)
        {
            ViewData["Events"] = data.Where(u => u.ShowPrevious == true).ToList();
        }
        else if(showUpcoming)
        {
            ViewData["Events"] = data.Where(u => u.ShowUpcoming == true).ToList();
        }
        return View();
    }
}

3.Controller:

public class HomeController : Controller
{

    public IActionResult ReloadEvents(bool showPrevious, bool showUpcoming)
    {
        return ViewComponent("Events", new { showPrevious = showPrevious, showUpcoming = showUpcoming });
    }
    public IActionResult Index()
    {
        var model = new Event() { ShowPrevious = true, ShowUpcoming = true };
        return View(model);
    }
}

4.Index.cshtml:

@model Event
@Html.CheckBoxFor(m => m.ShowPrevious, new { id = "cbShowPrevious", onchange = "ReloadEvents()" })
@Html.CheckBoxFor(m => m.ShowUpcoming, new { id = "cbShowUpcoming", onchange = "ReloadEvents()" })
<div id="events">
    @await Component.InvokeAsync("Events", new { showPrevious = Model.ShowPrevious, showUpcoming = Model.ShowUpcoming })
</div>

@section Scripts
{
<script>
    function ReloadEvents() {
        $.ajax({
        url: '@Url.Action("ReloadEvents", "Home")',
        data: {
        showPrevious: document.getElementById("cbShowPrevious").checked,
        showUpcoming: document.getElementById("cbShowUpcoming").checked
            },
            success: function (data) {
                $("#events").html(data);
            }
        })
} 
</script> 
}

5.Default.cshtml(the view component Razor view):

@model Event
@{
    List<Event> events = ViewData["Events"] as List<Event>;
    if (events.Count > 0)
    {
        <table>
            <tr>
                <th>ShowPrevious</th>
                <th>ShowUpcoming</th>
                <th>Data</th>
            </tr>
            <tbody>
                @foreach (var item in events)
                {
                    <tr>
                        <td>@item.ShowPrevious</td>
                        <td>@item.ShowUpcoming</td>
                        <td>@item.Data</td>
                    </tr>
                }

            </tbody>
        </table>
    }
}

Result: enter image description here

Roldan answered 10/3, 2020 at 6:10 Comment(2)
Thanks, Rena. Looks like all I was missing was the success function call. Thank you so much for your help, I've got it working now.Dismal
i got "the server responded with a status of 500 " error with this solutionMobster

© 2022 - 2024 — McMap. All rights reserved.