Search code examples
jqueryasp.net-core-mvcrazor-pagesasp.net-core-viewcomponent

Modal as ViewComponent Not Displaying Data


I'm trying to implement my first solution using Razor Pages and ViewComponents in ASP.NET MVC Core 2 and I'm having an issue.

Specifically, I have a list of items displaying on a Razor Page. Each item in the list has a button on it. When this button is clicked, I want to pass 2 parameters to a ViewComponent (which is a bootstrap modal) and display the modal. The problem is I can't get the data to display.

Specifically, I'd only like to invoke the ViewComponent after the button is clicked, not when the parent page is rendered. I don't think I have the "flow" correct. At any rate, here is what I have so far:

Parent Razor Page with list of items and call to ViewComponent:

@foreach (var item in Model.SearchResults)
{
    items
}

@await Component.InvokeAsync("Location")

Jquery $.get call to controller passing parameters to controller to generate modal data:

thisdata = $(this).attr('data-author');
 searchString = $(location).attr('href').split("=")[1];

  $.get("/Search/GetLocations", { "author": thisdata, "searchString": searchString })
            .done(function (data, textStatus, jqXHR) {

            })
            .fail(function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);

            });

Controller Action which generates the data for the Modal:

public ViewComponentResult GetLocations(string author, string searchString)
{
    var model = _tclRepository.GetLocations(author, searchString);

    return ViewComponent("Location", model);
}

The ViewComponent:

public IViewComponentResult Invoke(IEnumerable<LocationViewModel> model)
{
    if (model == null)
    {
        var x = Enumerable.Empty<Data.ViewModels.LocationViewModel>().ToList();
         return View(x);
     }
     else
     {
         return View(model);
  }
}

Portion of default.cshtml which is bootstrap 4 modal:

<div class="modal-body">
    <table class="table">
        <thead class="thead-dark">
            <tr>
                <th scope="col">Copy #</th>
                <th scope="col">Branch</th>
                <th scope="col">Status</th>
                <th scope="col">Date Due</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <th scope="row">1</th>
                        <td>@item.Branch</td>
                        <td>@item.Status</td>
                        <td>@item.DueDate</td>
                 </tr>
             }
    </tbody>
  </table>
 </div>

Any help is much appreciated,

Thanks,

Pete


Solution

  • In my case I had to update the Modal via a Jquery get.

    So on the "parent" page invoke the ViewComponent:

    @await Component.InvokeAsync("Location")
    

    After a button click on one of the items in the "parent" page, execute a jquery "get" passing in the parameters and populating the model for the ViewComponent. Then I had to update the Viewcomponent's "default.html" with the new data as shown below. This is what worked for me. Although I'm not convinced it's the "best" solution so your mileage may vary (as they say).

    ~ Pete

     $('button').click(function (e) {
    
            var author = $(this).data('author');
            var searchString = $(location).attr('href').split("=")[1];
    
            e.preventDefault();
            $.get("/Search/GetLocations", { "author": author, "searchString": searchString })
                .done(function (data, textStatus, jqXHR) {
                    console.log(data);
    
                    $('.table').find("tr:gt(0)").remove();
                    var row = $(data).find('tbody').html();
                    $('.table > thead').append(row);
    
                })
                .fail(function (jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                });
        });