Un composant Blazor flexible pour afficher des indicateurs de chargement avec support pour des images personnalisées, du texte et du contenu custom. Inclut interception HTTP automatique avec retry intelligent, exponential backoff, métriques en temps réel et annulation globale. | A flexible Blazor component for displaying loading indicators with support for custom images, text and custom content. Includes automatic HTTP interception with smart retry, exponential backoff, real-time metrics and global cancellation.
$ dotnet add package Blazor.FlexLoaderUn composant Blazor flexible et reutilisable pour afficher des indicateurs de chargement avec support pour des images personnalisees, du texte et du contenu custom. Inclut un SVG anime par defaut !
dotnet add package Blazor.FlexLoader
Program.csusing Blazor.FlexLoader.Extensions;
builder.Services.AddBlazorFlexLoader();
_Imports.razor@using Blazor.FlexLoader.Components
@using Blazor.FlexLoader.Services
<FlexLoader />
C'est tout ! Le loader affichera automatiquement un SVG anime professionnel.
Program.csusing Blazor.FlexLoader.Extensions;
// Configure le loader avec interception automatique des requetes HTTP
builder.Services.AddBlazorFlexLoaderWithHttpInterceptor(client =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
// Autres configurations du HttpClient...
});
_Imports.razor@using Blazor.FlexLoader.Components
@using Blazor.FlexLoader.Services
<FlexLoader />
Avantages:
HttpRequestExceptionShow() et Close()using Blazor.FlexLoader.Extensions;
builder.Services.AddBlazorFlexLoaderWithHttpInterceptor(
client =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
client.Timeout = TimeSpan.FromSeconds(30);
},
options =>
{
// Retry avec exponential backoff
options.MaxRetryAttempts = 5;
options.UseExponentialBackoff = true; // 1s, 2s, 4s, 8s, 16s...
options.RetryDelay = TimeSpan.FromSeconds(1);
// Intercepte uniquement les routes API
options.InterceptPredicate = request =>
request.RequestUri?.AbsolutePath.StartsWith("/api/") ?? false;
// Affiche le loader uniquement pour les mutations
options.ShowLoaderPredicate = request =>
request.Method != HttpMethod.Get;
// Callback avant chaque retry
options.OnRetry = async (attempt, exception, delay) =>
{
Console.WriteLine($"Tentative {attempt} apr�s {delay.TotalSeconds}s");
};
// Active le logging d�taill� en d�veloppement
options.EnableDetailedLogging = builder.Environment.IsDevelopment();
});
?? Voir la documentation compl�te des options
@inject IHttpClientFactory HttpClientFactory
<button @onclick="FetchData">Charger les donnees</button>
@code {
private async Task FetchData()
{
// Le loader s'affiche automatiquement !
var client = HttpClientFactory.CreateClient("BlazorFlexLoader");
var response = await client.GetAsync("/api/data");
// Le loader se masque automatiquement a la fin
// Retry automatique en cas d'erreur !
}
}
@inject LoaderService LoaderService
<button @onclick="ShowLoader">Afficher le loader</button>
@code {
private async Task ShowLoader()
{
LoaderService.Show(); // Affiche le SVG anime par defaut
try
{
await SomeAsyncOperation();
}
finally
{
LoaderService.Close(); // Masque le loader
}
}
}
<!-- Loader par defaut avec SVG anime -->
<FlexLoader />
<!-- Loader avec image personnalisee -->
<FlexLoader ImagePath="/images/custom-loader.gif" />
<!-- Loader avec contenu custom -->
<FlexLoader>
<CustomContent>
<div class="spinner-border" role="status"></div>
</CustomContent>
</FlexLoader>
LoaderService.Increment(); // Compter +1
LoaderService.Decrement(); // Compter -1
LoaderService.Reset(); // Forcer fermeture
| Parametre | Type | Defaut | Description |
|---|---|---|---|
ImagePath | string? | null | Chemin vers l'image (si null = SVG par defaut) |
Text | string? | "Chargement..." | Texte affiche pendant le chargement |
BackgroundColor | string | "rgba(255,255,255,0.75)" | Couleur de fond de l'overlay |
TextColor | string | "#333" | Couleur du texte |
ImageHeight | string? | "120px" | Hauteur de l'image (n'affecte pas le SVG) |
UseAbsolutePosition | bool | true | Position absolue ou fixe |
CustomContent | RenderFragment? | null | Contenu personnalise |
AutoClose | bool | true | Fermeture automatique avec delai |
AutoCloseDelay | int | 300 | Delai avant fermeture (ms) |
CloseOnOverlayClick | bool | false | Fermer au clic sur l'overlay |
public class LoaderService
{
public bool IsLoading { get; }
// Methodes simples
public void Show(); // Afficher
public void Close(); // Masquer
// Methodes avancees
public void Increment(); // Compter +1
public void Decrement(); // Compter -1
public void Reset(); // Forcer fermeture
public event EventHandler? OnChange;
}
// Configuration basique
services.AddBlazorFlexLoader();
// Configuration avec interception HTTP (options par d�faut)
services.AddBlazorFlexLoaderWithHttpInterceptor(client =>
{
client.BaseAddress = new Uri("https://api.example.com");
client.Timeout = TimeSpan.FromSeconds(30);
});
// Configuration avec interception HTTP + options personnalis�es ??
services.AddBlazorFlexLoaderWithHttpInterceptor(
client =>
{
client.BaseAddress = new Uri("https://api.example.com");
},
options =>
{
options.MaxRetryAttempts = 5;
options.UseExponentialBackoff = true;
options.RetryDelay = TimeSpan.FromSeconds(2);
options.RetryOnStatusCodes = new HashSet<HttpStatusCode>
{
HttpStatusCode.InternalServerError,
HttpStatusCode.BadGateway,
HttpStatusCode.ServiceUnavailable
};
options.InterceptPredicate = request =>
request.RequestUri?.AbsolutePath.StartsWith("/api/") ?? false;
});
| Option | Type | D�faut | Description |
|---|---|---|---|
MaxRetryAttempts | int | 3 | Nombre maximum de tentatives |
RetryDelay | TimeSpan | 1s | D�lai de base entre les tentatives |
UseExponentialBackoff | bool | true | Augmentation exponentielle du d�lai |
RetryOnStatusCodes | HashSet<HttpStatusCode> | [500,502,503,504,408] | Codes HTTP d�clenchant un retry |
RetryOnTimeout | bool | true | Retry en cas de timeout |
InterceptPredicate | Func<HttpRequestMessage, bool>? | null | Filtre les requ�tes � intercepter |
ShowLoaderPredicate | Func<HttpRequestMessage, bool>? | null | Filtre l'affichage du loader |
OnRetry | Func<int, Exception?, TimeSpan, Task>? | null | Callback avant chaque retry |
EnableDetailedLogging | bool | false | Active le logging d�taill� |
L'HttpCallInterceptorHandler intercepte automatiquement toutes les requetes HTTP et:
ShowLoaderPredicate)HttpRequestException (probleme reseau)RetryOnTimeout = true)Le handler utilise ILogger<HttpCallInterceptorHandler> automatiquement si disponible :
// Dans Program.cs
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Information);
Logs g�n�r�s :
LogInformation : D�but/fin de requ�te avec dur�eLogWarning : Tentatives de retryLogError : �checs apr�s toutes les tentativesLogDebug : D�tails techniques (si EnableDetailedLogging = true)options.InterceptPredicate = request =>
request.RequestUri?.AbsolutePath.StartsWith("/api/") ?? false;
options.ShowLoaderPredicate = request =>
request.Method == HttpMethod.Post ||
request.Method == HttpMethod.Put ||
request.Method == HttpMethod.Delete;
@inject INotificationService Notifications
options.OnRetry = async (attempt, exception, delay) =>
{
await Notifications.ShowWarning($"Tentative {attempt}...");
};
MIT
A flexible and reusable Blazor component for displaying loading indicators with support for custom images, text, and custom content. Includes animated SVG by default!
dotnet add package Blazor.FlexLoader
Program.csusing Blazor.FlexLoader.Extensions;
builder.Services.AddBlazorFlexLoader();
_Imports.razor@using Blazor.FlexLoader.Components
@using Blazor.FlexLoader.Services
<FlexLoader />
That's it! The loader will automatically display a professional animated SVG.
Program.csusing Blazor.FlexLoader.Extensions;
// Configure the loader with automatic HTTP request interception
builder.Services.AddBlazorFlexLoaderWithHttpInterceptor(client =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
// Other HttpClient configurations...
});
_Imports.razor@using Blazor.FlexLoader.Components
@using Blazor.FlexLoader.Services
<FlexLoader />
Benefits:
HttpRequestExceptionShow() and Close()using Blazor.FlexLoader.Extensions;
builder.Services.AddBlazorFlexLoaderWithHttpInterceptor(
client =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
client.Timeout = TimeSpan.FromSeconds(30);
},
options =>
{
// Retry with exponential backoff
options.MaxRetryAttempts = 5;
options.UseExponentialBackoff = true; // 1s, 2s, 4s, 8s, 16s...
options.RetryDelay = TimeSpan.FromSeconds(1);
// Intercept only API routes
options.InterceptPredicate = request =>
request.RequestUri?.AbsolutePath.StartsWith("/api/") ?? false;
// Show loader only for mutations
options.ShowLoaderPredicate = request =>
request.Method != HttpMethod.Get;
// Callback before each retry
options.OnRetry = async (attempt, exception, delay) =>
{
Console.WriteLine($"Retry attempt {attempt} after {delay.TotalSeconds}s");
};
// Enable detailed logging in development
options.EnableDetailedLogging = builder.Environment.IsDevelopment();
});
?? See full options documentation
@inject IHttpClientFactory HttpClientFactory
<button @onclick="FetchData">Load data</button>
@code {
private async Task FetchData()
{
// Loader displays automatically!
var client = HttpClientFactory.CreateClient("BlazorFlexLoader");
var response = await client.GetAsync("/api/data");
// Loader hides automatically when done
// Automatic retry on errors!
}
}
@inject LoaderService LoaderService
<button @onclick="ShowLoader">Show loader</button>
@code {
private async Task ShowLoader()
{
LoaderService.Show(); // Shows the default animated SVG
try
{
await SomeAsyncOperation();
}
finally
{
LoaderService.Close(); // Hide the loader
}
}
}
<!-- Loader par defaut avec SVG anime -->
<FlexLoader />
<!-- Loader avec image personnalisee -->
<FlexLoader ImagePath="/images/custom-loader.gif" />
<!-- Loader avec contenu custom -->
<FlexLoader>
<CustomContent>
<div class="spinner-border" role="status"></div>
</CustomContent>
</FlexLoader>
LoaderService.Increment(); // Compter +1
LoaderService.Decrement(); // Compter -1
LoaderService.Reset(); // Forcer fermeture
| Parametre | Type | Defaut | Description |
|---|---|---|---|
ImagePath | string? | null | Chemin vers l'image (si null = SVG par defaut) |
Text | string? | "Chargement..." | Texte affiche pendant le chargement |
BackgroundColor | string | "rgba(255,255,255,0.75)" | Couleur de fond de l'overlay |
TextColor | string | "#333" | Couleur du texte |
ImageHeight | string? | "120px" | Hauteur de l'image (n'affecte pas le SVG) |
UseAbsolutePosition | bool | true | Position absolue ou fixe |
CustomContent | RenderFragment? | null | Contenu personnalise |
AutoClose | bool | true | Fermeture automatique avec delai |
AutoCloseDelay | int | 300 | Delai avant fermeture (ms) |
CloseOnOverlayClick | bool | false | Fermer au clic sur l'overlay |
public class LoaderService
{
public bool IsLoading { get; }
// Methodes simples
public void Show(); // Afficher
public void Close(); // Masquer
// Methodes avancees
public void Increment(); // Compter +1
public void Decrement(); // Compter -1
public void Reset(); // Forcer fermeture
public event EventHandler? OnChange;
}
// Basic configuration
services.AddBlazorFlexLoader();
// HTTP interception with default options
services.AddBlazorFlexLoaderWithHttpInterceptor(client =>
{
client.BaseAddress = new Uri("https://api.example.com");
client.Timeout = TimeSpan.FromSeconds(30);
});
// HTTP interception with custom options ??
services.AddBlazorFlexLoaderWithHttpInterceptor(
client =>
{
client.BaseAddress = new Uri("https://api.example.com");
},
options =>
{
options.MaxRetryAttempts = 5;
options.UseExponentialBackoff = true;
options.RetryDelay = TimeSpan.FromSeconds(2);
options.RetryOnStatusCodes = new HashSet<HttpStatusCode>
{
HttpStatusCode.InternalServerError,
HttpStatusCode.BadGateway,
HttpStatusCode.ServiceUnavailable
};
options.InterceptPredicate = request =>
request.RequestUri?.AbsolutePath.StartsWith("/api/") ?? false;
});
| Option | Type | Default | Description |
|---|---|---|---|
MaxRetryAttempts | int | 3 | Maximum number of retry attempts |
RetryDelay | TimeSpan | 1s | Base delay between attempts |
UseExponentialBackoff | bool | true | Exponential delay increase |
RetryOnStatusCodes | HashSet<HttpStatusCode> | [500,502,503,504,408] | HTTP codes triggering retry |
RetryOnTimeout | bool | true | Retry on timeout |
InterceptPredicate | Func<HttpRequestMessage, bool>? | null | Filter requests to intercept |
ShowLoaderPredicate | Func<HttpRequestMessage, bool>? | null | Filter loader display |
OnRetry | Func<int, Exception?, TimeSpan, Task>? | null | Callback before each retry |
EnableDetailedLogging | bool | false | Enable detailed logging |
The HttpCallInterceptorHandler automatically intercepts all HTTP requests and:
ShowLoaderPredicate)HttpRequestException (network issues)RetryOnTimeout = true)The handler uses ILogger<HttpCallInterceptorHandler> automatically if available:
// In Program.cs
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Information);
Generated logs:
LogInformation: Request start/end with durationLogWarning: Retry attemptsLogError: Failures after all attemptsLogDebug: Technical details (if EnableDetailedLogging = true)options.InterceptPredicate = request =>
request.RequestUri?.AbsolutePath.StartsWith("/api/") ?? false;
options.ShowLoaderPredicate = request =>
request.Method == HttpMethod.Post ||
request.Method == HttpMethod.Put ||
request.Method == HttpMethod.Delete;
@inject INotificationService Notifications
options.OnRetry = async (attempt, exception, delay) =>
{
await Notifications.ShowWarning($"Tentative {attempt}...");
};
MIT