A Blazor library for showing spinners, error and success messages during asynchronous method calls
Find a file
2023-02-07 16:35:58 +01:00
.idea/.idea.Ramboe.Blazor.dir/.idea init 2022-12-23 11:10:53 +01:00
ComponentBaseExtensions cleanups 2023-02-03 01:51:46 +01:00
DependencyInjection finished startup configuration fluent api 2023-02-06 11:20:07 +01:00
ExtensionMethods cleanups 2023-02-03 01:51:46 +01:00
Feedback finished startup configuration fluent api 2023-02-06 11:20:07 +01:00
Models introduced configuration via depedency injection 2023-02-05 19:49:40 +01:00
Services cleanups 2023-02-03 01:51:46 +01:00
wwwroot refactorings, also debugging improvements 2023-02-03 01:20:31 +01:00
.gitignore init 2022-12-23 11:10:53 +01:00
_Imports.razor Initial Setup, documentation and cleanup next 2022-12-24 19:18:10 +01:00
Constants.cs finished startup configuration fluent api 2023-02-06 11:20:07 +01:00
ExampleJsInterop.cs cleanups 2023-02-03 01:51:46 +01:00
FeedbackArea.razor finished startup configuration fluent api 2023-02-06 11:20:07 +01:00
FeedbackArea.razor.cs finished startup configuration fluent api 2023-02-06 11:20:07 +01:00
logo-icon.png added nuget package 2023-02-07 15:29:37 +01:00
logo-icon.svg added nuget package 2023-02-07 15:29:37 +01:00
Ramboe.Blazor.UserFeedback.csproj added nuget package 2023-02-07 15:29:37 +01:00
README.md Update README.md 2023-02-07 16:35:58 +01:00

Ramboe.Blazor.UserFeedback

Ramboe UserFeedback - A Blazor library for showing spinners, error and success messages during asynchronous method calls. This framework simplifies the handling of asynchronous UI updates, allowing developers to focus on their core logic and providing a seamless user experience.

With its easy-to-use API, this library makes it simple to display spinners, error messages, and success messages for asynchronous method calls. Give your users the feedback they need, without sacrificing simplicity or performance.

Add the nuget package to your blazor server / wasm project

dotnet add package Ramboe.Blazor.UserFeedback --version 1.0.0

Functionality

The basic functionality is to display a spinner while a function is executed

and display any exceptions that might occur (UI remains still responsive)

you can also display a loading message beneath the spinner

and optionally display a success message (e.g. for successful http posts)

Anatomy

Areas

First make your component inherit from TryWrapper

then wrap the FeedbackArea around the HTML markup that you want to hide while spinner is active

the component's code should look like this

@inherits Ramboe.Blazor.UserFeedback.ComponentBaseExtensions.TryWrapper

<FeedbackArea Target="DefaultTarget">
    <table class="table">
        <thead>
        <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
        </tr>
        </thead>
        <tbody>
        @foreach (var forecast in forecasts)
        {
            <tr>
                <td>@forecast.Date.ToShortDateString()</td>
                <td>@forecast.TemperatureC</td>
                <td>@forecast.TemperatureF</td>
                <td>@forecast.Summary</td>
            </tr>
        }
        </tbody>
    </table>
</FeedbackArea>

FeedbackArea takes several parameters if you need to customize the spinner for a certain area within your application

Targets

In order to determine which area is to spin while we are executing stuff, we need to attach a FeedbackTarget to it, which is responsible for holding the state of the feedback area (spinner active, success message shown, etc..)

since we inherit from trywrapper, we always get at least one target that we can use, the DefaultTarget

if you need more targets, simply add them to your component (don't forget to initialize with "new()")

Usage

Setting up configuration on startup

Feedback areas need to be configured at startup. You can use the AddStandardFeedbackAreas() method

which applies the following configuration

  • SpinnerSizeMode = SpinnerSizeMode.Vh5,

  • ColorMode = ColorMode.Primary,

  • SpinnerType = SpinnerType.BorderSpinner

you can also use fluent api that comes along with AddAndConfigureFeedbackAreas() if you want to configure the styling yourself

WithColor() also has an overload that works with the ColorMode enum

Configuring the Spinner

The following attributes can be configured: Size, Color, Type

Size: configured through SpinnerSizeMode enum, which ranges from vh2 - vh90

Color: configured through SpinnerColorMode enum, which represents the color categories that come with bootstrap (primary, secondary, success, ...)

Type: configured through SpinnerTypeMode enum, which currently contais spinner-border and spinner-grow

Remember: parameters override startup config

any parameters passed directly into a FeedbackArea will override any configuration done in Program.cs. For example setting "primary" color mode on FeedbackArea #2 ...

results in that FeedbackAreas spinner color being set to "primary", while FeedbackArea #1 just takes the startup configuration:

Finally: Making it spin

It works the same way as EventCallbacks. If you want to have the spinner spinning while a certain method is executed, 2 steps are needed:

  1. declare the method as usual
    async Task<List<WeatherForecast>> LoadData()
    {
        // simulate waiting for an api, so we can actually see the spinner spinning
        await Task.Delay(2000);

        return await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
    }
  1. pass your method and it's according target simply into one of the "TryAsync" overloads
  protected override async Task OnInitializedAsync()
    {
        forecasts = await TryAsync(LoadData, DefaultTarget);

        forecasts = await TryAsync(LoadData, DefaultTarget, "loading with loading message but without success message");

        forecasts = await TryAsync(LoadData, DefaultTarget, "loading with success message", "updating data successful");
                
    }

you can also use one of the explicit methods

  protected override async Task OnInitializedAsync()
    {        
        // those to methods do the same thing

        forecasts = await TryAsync(LoadData, DefaultTarget, "loading with success message", "updating data successful");
    
        forecasts = await TryWithLoadingAndSuccessMessageAsync(LoadData, DefaultTarget, "loading with success message, explicit", "updating data successful")
    }

Since it works the same way as EventCallbacks, you know already that you need a Lambda expression for Methods that take parameters:

  protected override async Task OnInitializedAsync()
    {        
        await LambdaExample();
    }

  async Task LambdaExample()
    {
        await Task.Delay(2000);

        forecasts = await TryAsync(
            () => ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now)),
            DefaultTarget,
            "loading, lambda",
            "lambda successfull"
        );
    }

Summary

configure FeedbackAreas on startup:

builder.Services.AddAndConfigureFeedbackAreas()
       .WithSize(SpinnerSizeMode.Vh5)
       .WithType(SpinnerTypeMode.BorderSpinner)
       .WithColor(SpinnerColorMode.Secondary)
    .ConfigureFeedbackAreas();

Inherit from TryWrapper and wrap a FeedbackArea (including target) around your content

@inherits Ramboe.Blazor.UserFeedback.ComponentBaseExtensions.TryWrapper

<FeedbackArea Target="DefaultTarget">
    @*Content here*@
</FeedbackArea>

You can use the various overloads..

forecasts = await TryAsync(LoadData, DefaultTarget);

forecasts = await TryAsync(LoadData, DefaultTarget, "loading with loading message but without success message");

forecasts = await TryAsync(LoadData, DefaultTarget, "loading with success message", "updating data successful");

...or be explicit

  protected override async Task OnInitializedAsync()
    {
        forecasts = await TryWithLoadingAndSuccessMessageAsync(LoadData, DefaultTarget, "loading with success message, explicit", "updating data successful")
              
    }

Methods are passed into FeedbackArea as delegates, meaning Lambda expressions are needed when working with parameters (just as in EventCallbacks).