Search code examples
javascriptasp.net-mvcmodel-view-controllerget

asp-mvc get function in javascript not displaying updated model values


So i am trying to achieve the best (most user friendly and performant) way of having a html table updated with data that is queried for in a searchbox.

The user can search for something by typing in a searchbox, i want to reload that html table with no (visible) postbacks/reloads (if possible) and have it behave like it is dynamically refreshing the data.

What i have and what i am currently doing is the following: A Razor Html.TextBox(...) and a Javascript function that looks like this:

  $(function () {
        $('#txtSearchString').keyup(function () {
                  //Content to send
                  var searchvalue = $(this).val();
                  $.get('@Url.Action("Customers", "Home")', { "SearchValue": searchvalue });
                });
            });

Where 'txtSearchString' is the name/id of the Html.TextBox. When i type something in this txtbox, it goes to a HttpGet Action where i receive the 'searchvalue' and i query my database and return results matching my requirements. NOTE that this Action is the same action as the initial one that is loaded.

I than return my model (where this updated data resides), i can also clearly see when debugging that i have update results in my controller as well in my view when iterating over the list of results (ex, initial list contains 100 items, updated list contains 20) but still when the view is loaded, i am seeing the same results as initially loaded, it doesn't seem to upload the view in the browser.

I have no idea why this is so. I don't know if this is the best way of doing what i want to, i have no experience in Partial views and don't know if i better use that instead, but still whatever i end up using, i want to understand whats happening behind and resulting in this behavior.

If you have any question, need more clarification on anything, please ask me. Kind regards!

UPDATE:

This is how i populate/update my html table with the values from my model:

<table class="table table-hover trCursor">
<thead>
    <tr>
        <th scope="col">
            @Html.ActionLink("Id", "Customers", new { sortOrder = ViewBag.DateSortParm })
        </th>
        <th scope="col">
            @Html.ActionLink("Name", "Customers", new { sortOrder = ViewBag.NameSortParm })
        </th>      
        <th>...</th>

    </tr>
</thead>
@foreach (var customer in Model.Customers)
{
    <tr onclick="location.href='@(Url.Action("CustomerDetail", "Customer", new { Id = customer.ID }))'">

        @Html.HiddenFor(c => customer.ID)

        <td scope="row">@customer.ID</td>
        <td>@customer.CustomerName</td>
        <td>...</td>

    </tr>
}

Where i can see that "Model.Customers" has the updated values when iterating over it.


Solution

  • When you use ajax (your $.get() function, you are making a call to a server method which in you case returns html, but you then need to do something with it - in your case, add it to the DOM in the `success callback.

    Because you are only interested in updating the <tbody> in your view to display the filtered rows, your method should return a partial view of only that, so start by creating a partial, say _Customers.cshtl

    @model IEnumerable<Customer>
    @foreach(var customer in Model)
    {
        <tr>
            ... // add <td> elements
        </tr>
    }
    

    and delete the @foreach (var customer in Model.Customers){ ... } code in the main view and replace with

    <tbody id="customers">
        @{ Html.RenderPartial("_Customers", Model.Customers); }
    </tbody>
    

    Now create a separate controller method, say

    public PartialViewResult FetchCustomers(string search)
    {
        var customers = ... // your code to get Customers based on the search string
        return PartialView("_Customers", customers);
    }
    

    and modify the ajax call to update the table body in the success callback

    var customers = $('#customers');
    var url = '@Url.Action("Customers", "Home"';
    $('#txtSearchString').keyup(function () {
        var searchValue = $(this).val();
        $.get(url, { search : searchvalue }, function(response) {
            customers.html(response);
        });
    });
    

    However, since you are initially displaying all Customers in the view, there is no need to make an ajax call in this case (and doing on each .keyup event will affect performance), since the data is already in the DOM. Instead you can just use javaScript to loop each row in the table body, and show or hide roes based on the search string. For a simple example, refer Filter table rows based on select value.