d00d
d00d

Reputation: 763

Spinner does not show b/c the bound variable is not updated

I'm working on a Blazor server side app. The page has a table with a list of cars and some filter elements on top. When I select a filter, a spinner should be visible until the new data is fetched and rendered.

The spinner with its variable:

<div class="spinner-border @spinner" role="status">
    <span class="visually-hidden">Loading...</span>
</div>

@code{
string spinner = "invisible";

    public string vehicleTypeFilter
    {
        set
        {
            _vehicleTypeFilter = value;            
            ApplyFilters();
        }
        get { return _vehicleTypeFilter; }
    }
}

The select for the Baumuster (vehicleType) is bound to the vehicleTypeFilter variable:

<div class="col-md-2 form-floating">
        <select class="form-control" @bind="vehicleTypeFilter">
            <option value="" selected>Alle</option>
            @foreach (var vehicleType in vehicleTypes.OrderBy(x => x.Description))
            {
                <option value="@vehicleType.Description">@vehicleType.Description</option>
            }
        </select>
        <label>Baumuster</label>
    </div>

Then a value is selected, the ApplyFilter method is triggered through the setter of the vehicleTypeFilter variable:

public void ApplyFilters()
{
        ToggleSpinner();
        // I also tried a StateHasChanged(); right here

        // 1. Get all cars
        cars = model.CreateIndexViewModel();
      
        // 2. Filter for Baumuster / vehicle type
        if (!string.IsNullOrEmpty(vehicleTypeFilter))
        {
            cars.viewModels = cars.viewModels.Where(x => x.VehicleDescription == vehicleTypeFilter).ToList();
        }

        ToggleSpinner();
}

The ToggleSpinner method:

public void ToggleSpinner()
    {
        if (spinner == "invisible" )
            spinner = "";
        else
            spinner = "invisible";
    }

Unfortunately, I don't see the spinner. When I inspect the html page right after the breakpoint hits the Baumuster-filter, the value of spinner is still set to "invisible". I even tried to call StateHasChanged(); after the first ToggleSpinner() but that didn't help.

enter image description here

Upvotes: 1

Views: 165

Answers (2)

Bennyboy1973
Bennyboy1973

Reputation: 4216

You've shown a lot of code, but I don't see ToggleSpinner

However, you call it twice in your ApplyFilters method, with no blocking calls, so I'd assume that it's turning the spinner on and off so fast that it doesn't render (or at least that you can't notice it).

If the methods you call in ApplyFilters actually take any time, then Henk's got the right idea-- except you should use async Task I think.

Upvotes: 2

Henk Holterman
Henk Holterman

Reputation: 273464

Your problem is that you want async behaviour from a synchronous property. The standard advice is against async void but if you want to stay with the property, the minimal change would be:

public async void ApplyFilters()
{
   ToggleSpinner();
   // I also tried a StateHasChanged(); right here
   StateHasChanged();   // this _requests_ an update
   await Task.Delay(1); // this is why you need async void

   ... as before

   ToggleSpinner();
   StateHasChanged();
}

Upvotes: 1

Related Questions