Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
285 views
in Technique[技术] by (71.8m points)

asp.net - Footer showing first when Blazor web application loads

I have a Blazor .net core hosted application. When the site runs, the footer shows for a few seconds while the app does authorizing. Is there any way to show a loading indicator whenever there is some activity running? I am specifically referring to when the app is authorizing. I want the contents to load before showing the footer? Please see screenshot.

enter image description here

question from:https://stackoverflow.com/questions/65896236/footer-showing-first-when-blazor-web-application-loads

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Based on your description, an "AppState" approach could be useful if I understood it correctly. It's a way to enable communication between components at any level in their hierarchy.

Let's start by defining the AppState. This class uses the .NET events to raise a notification when a value has changed.

public class AppState
{
    private Boolean _loadingIsFinished = false;

    public Boolean LoadingIsFinished
    {
        get => _loadingIsFinished;
        set
        {
            _loadingIsFinished = value;
            AppStateChanged?.Invoke(this, EventArgs.Empty);
        }
    }

    public event EventHandler AppStateChanged;
}

The AppState is added to the dependency injection system. For Blazor WASM, it should be a singleton dependency. For Blazor Server, though, it should be a scoped one.

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("#app");

    ...
    builder.Services.AddSingleton(new AppState());
    ... 
   
    await builder.Build().RunAsync();
}

The Footer component uses this state and subscribe to the change event and update a local field. This field is used to determine if the footer is displayed or not. As a good practice, the Footer implements the IDisposable to unsubscribe from the event.

@inject AppState _appState
@implements IDisposable

@if (_showFooter == true)
{
    <div class="footer">
        @*Footer Content*@
    </div>
}

@code {

    private Boolean _showFooter = false;

    protected override void OnInitialized()
    {
        base.OnInitialized();

        _appState.AppStateChanged += AppStateChanged;

        _showFooter = _appState.LoadingIsFinished;
    }

    private async void AppStateChanged(object sender, EventArgs args)
    {
        _showFooter = _appState.LoadingIsFinished;
        await InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        _appState.AppStateChanged -= AppStateChanged;
    }
}

Because the update of the AppState can happen out of band, we force the UI to update by calling StateHasChanged. Besides, the call is wrapped inside InvokeAsync to make sure it is handled correctly by the UI.

In every other component, you can inject the AppState and change the value of LoadingIsFinished. Assuming you have a Dashboard component, you could use the AppState like this.

@inject AppState _appstate

<h3>Dashboard</h3>

@code {

    protected override void OnInitialized()
    {
        base.OnInitialized();
        _appstate.LoadingIsFinished = true;
    }
}

AppState coupled to authentication

If your question is more about authentication, there is a specialized way to do it. You can inject AuthenticationStateProvider into the AppState, introduce a new property like IsAuthenticated and use this property in your Footer component.

 public AppState(AuthenticationStateProvider authStateProvider)
{
    _authStateProvider = authStateProvider;
    _authStateProvider.AuthenticationStateChanged += HandleAuthStateChanged;
}

private async void HandleAuthStateChanged(Task<AuthenticationState> task)
{
    var state = await task;
    IsAuthentication = state.User != null && state.User.Claims.Any();
}

public void Dispose()
{
    _authStateProvider.AuthenticationStateChanged -= HandleAuthStateChanged;
}

public event EventHandler AppStateChanged;

private Boolean _isAuthenticated = false;
public Boolean IsAuthenticated
{
    get => _isAuthenticated;
    set
    {
        _isAuthenticated = value;
        AppStateChanged?.Invoke(this, EventArgs.Empty);
    }
}

This is a fundamental version of an "AppState". However, there are frameworks like Fluxor for all these state transitions, or you could use a more decoupled way like a message bus for components, called ComponentBus.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...