Reputation: 763
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.
Upvotes: 1
Views: 165
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
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