Search code examples
javascriptjqueryasp.net-coreasp.net-ajaxpartial-views

ASP.NET Core conditionally load partial view on user search keyword input


We have a web application that shows a lot of (big) tables. For a user friendly UI we have implemented search (filter) as you type using ajax and loading partial views.

In short:

  1. input control tbSearch with a listener for the keyup event:
.on('keyup', 'input.filter', function () {
    showList(this);
}
  1. showList() fetches a _PartialView from the Controller and then loads the filtered result in the div/table (section-list):
function showList(control) {
    
    // search text
    var searchString = $('#tbSearch').val();

    // url
    var url = 'mycontroller/myaction';

    //parameters
    var data = {
        searchString: searchString,
    };

    $('.section-list').load(url, data, function () {
        
    });
}

So far pretty basic partialview loading with ajax. And it works great most of the times.

There is a problem when a user types quickly and the query to search the database is a bit more complex. In such cases (since ajax.load is async) the showList() function can be triggered for a new searchstring before the previous search has even loaded. This can then result for the results of the actual keyword entered by the user to be overridden by one of the previous keywords.

Example, I start writing quickly into the searchbox:

  • m
  • my
  • mys
  • myse
  • mysea
  • mysearc
  • mysearch (STOP typing)

and instead of results showing data filtered to "mysearch" they can actually be for "mysea".

I was thinking of putting ajax get partialview code into a separate async function (that returns a Promise), add a counter (count keyups on the page) and wait for the ajax function to complete and if the counter matches the last request, separately load the inner html of the div... But this seems like a complex solution.

Any ideas (for a simpler solution)?


Solution

  • I managed to find a solution to keep the "search as you type" functionality with adding and checking against a counter and loading ajax result a bit differently:

    //counter
    var searchCounter = 0;
    
    function showList(control) {
        // counter 
        searchCounter++;
        var localCounter = searchCounter;
    
        // search text
        var searchString = $('#tbSearch').val();
    
        // url
        var url = 'mycontroller/myaction';
    
        //parameters
        var data = {
            searchString: searchString,
        };
    
        // ajax load partialview
        $.ajax({
            url: url,
            type: "POST",
            dataType: "html",
            data: data,
            success: function (partialViewHtml) {
                //only load, if counter is still a match
                if (localCounter === searchCounter) {
                    $(".section-list").empty().append(partialViewHtml);
                   
                }
            }
        });
    }