In my blazer app I am making an api call to a back end server that could take some time. I need to display feedback to the user, a wait cursor or a "spinner" image. How is this done in Blazor?
I have tried using CSS and turning the CSS on and off but the page is not refreshed until the call is completed. Any suggestions would be greatly appreciated.
@functions {
UserModel userModel = new UserModel();
Response response = new Response();
string errorCss = "errorOff";
string cursorCSS = "cursorSpinOff";
protected void Submit()
{
//Show Sending...
cursorCSS = "";
this.StateHasChanged();
response = Service.Post(userModel);
if (response.Errors.Any())
{
errorCss = "errorOn";
}
//turn sending off
cursorCSS = "cursorSpinOff";
this.StateHasChanged();
}
}
await Task.Delay(1)
or await Task.Yield();
to flush changesprivate async Task AsyncLongFunc() // this is an async task
{
spinning=true;
await Task.Delay(1); // flushing changes. The trick!!
LongFunc(); // non-async code
currentCount++;
spinning=false;
await Task.Delay(1); // changes are flushed again
}
Option 1 is a simple solution that runs ok but looks like a trick.
On January'2020. @Ed Charbeneau published BlazorPro.Spinkit project enclosing long processes into task to don't block the thread:
Ensure your LongOperation()
is a Task
, if it is not, enclose it into a Task
and await for it:
async Task AsyncLongOperation() // this is an async task
{
spinning=true;
await Task.Run(()=> LongOperation()); //<--here!
currentCount++;
spinning=false;
}
Because Blazor Server apps use pre-rendering the spinner will not appear, to show the spinner the long operation must be done in OnAfterRender.
Use OnAfterRenderAsync over OnInitializeAsync to avoid a delayed server-side rendering
// Don't do this
//protected override async Task OnInitializedAsync()
//{
// await LongOperation();
//}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await Task.Run(()=> LongOperation());//<--or Task.Delay(0) without Task.Run
StateHasChanged();
}
}
Learn more about how to write nice spinner you can learn from open source project BlazorPro.Spinkit, it contains clever samples.
See Henk Holterman's answer with blazor internals explanation.