1

Using Blazor (server-side), I have a simple button I'd like to change to a spinner like here when a search is being performed. I want the UI to temporarily display "Loading..." on the button while this happens.

I'm using an <InputForm> tag to render a form with an <InputSelect> and an <InputText> field. When I click the submit button the form's OnValidSubmit fires HandleSearch(). I would expect the ShowLoader to update the UI element right away but it doesn't until the GetDataAsync completes, then it never changes back to a Search button.

I suspect there is a better way to achieve this simple task. Any ideas?

Html:

<button type="submit" class="btn btn-primary mt-3">
    @if (ShowLoader)
    {
        <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
        <span>Loading...</span>
    }
    else
    {
        <span>Search</span>
    }
</button>

Code block:

@code {
    public class SearchBox
    {
        [Required]
        public string SearchValue { get; set; }
        public string SearchField { get; set; }
    }

    public SearchBox search = new SearchBox();
    public bool ShowLoader = default;

    protected async Task HandleSearch()
    {
        ShowLoader = true;
        try
        {
            var result = await functionsClient.GetDataAsync<Reservation>(FunctionsClientConstants.ReservationsPath + "?field=" + search.SearchField + "&value=" + search.SearchValue);
            Console.WriteLine(result);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }                   
        ShowLoader = false;
    }
}

GetDataAsync method:

public async Task<T> GetDataAsync<T>(string path)
{            
    HttpResponseMessage response = httpClient.GetAsync(path).Result;

    using HttpContent content = response.Content;
    return JsonConvert.DeserializeObject<T>(await content.ReadAsStringAsync());
}

Update:

I changed the try/catch block to use a await Task.Delay(2000) instead of my GET and the search button behaves as it should. You click the button and it changes to "Loading..." for 2 seconds then changes back.

p.s. I realize there is a better way to handle async JSON but I'm having an issue with my inbound payload causing a deserialization fault at the moment so I'm using Newtonsoft.Json instead. Right now my GET causes a fault but that shouldn't impact the rendering of the UI if I'm catching, should it??

Jason Shave
  • 2,462
  • 2
  • 29
  • 47
  • This code looks OK, "it doesn't until the GetDataAsync completes" should not happen. Show that functionsClient.GetDataAsync() method, it is doing something wrong. – H H Sep 29 '19 at 17:21
  • The GetDataAsync is crashing due to a JSON deserialization issue I have which is why I added the try/catch. I updated my testing behavior as well as the code block for the GET... – Jason Shave Sep 29 '19 at 17:37
  • It won't hurt to put a `StateHasChanged();` before the GetData() call. – H H Sep 29 '19 at 17:41
  • thx for the suggestion. just tried that...no change :( – Jason Shave Sep 29 '19 at 17:43
  • Adding `await Task.Delay(1)` before my async GET call worked! – Jason Shave Sep 29 '19 at 18:12
  • 1
    OK, but the core problem is `response = httpClient.GetAsync(path).Result;`, make that `response = await httpClient.GetAsync(path);`. Always avoid calling `.Result` – H H Sep 29 '19 at 18:22

0 Answers0