diff --git a/samples/Sample.Core/Pages/BusyButton/Index.razor b/samples/Sample.Core/Pages/BusyButton/Index.razor
index e27c7185..ad56de48 100644
--- a/samples/Sample.Core/Pages/BusyButton/Index.razor
+++ b/samples/Sample.Core/Pages/BusyButton/Index.razor
@@ -25,6 +25,7 @@
-
-
- Saving ...
+ Saving...
Save
@@ -50,6 +49,17 @@
+
+
+
+ Process
+
+
+
@code {
[Parameter]
public bool IsBusy { get; set; } = true;
@@ -57,4 +67,8 @@
[Parameter]
public bool IsDisabled { get; set; } = false;
+ public async Task Process()
+ {
+ await Task.Delay(2000);
+ }
}
diff --git a/src/LoreSoft.Blazor.Controls/BusyButton.cs b/src/LoreSoft.Blazor.Controls/BusyButton.cs
index 5c948884..e6ad37a0 100644
--- a/src/LoreSoft.Blazor.Controls/BusyButton.cs
+++ b/src/LoreSoft.Blazor.Controls/BusyButton.cs
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
+using Microsoft.AspNetCore.Components.Web;
namespace LoreSoft.Blazor.Controls;
@@ -11,6 +12,9 @@ public class BusyButton : ComponentBase
[Parameter]
public bool Disabled { get; set; }
+ [Parameter]
+ public string BusyText { get; set; } = "Processing";
+
[Parameter]
public RenderFragment BusyTemplate { get; set; }
@@ -20,30 +24,80 @@ public class BusyButton : ComponentBase
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary Attributes { get; set; } = new Dictionary();
+ [Parameter]
+ public EventCallback Trigger { get; set; }
+
+ private bool Executing { get; set; }
+
///
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "button");
builder.AddMultipleAttributes(1, Attributes);
- builder.AddAttribute(2, "disabled", Disabled || Busy);
+ builder.AddAttribute(2, "disabled", Disabled || IsBusy);
+
+ if (Trigger.HasDelegate)
+ {
+ builder.AddAttribute(3, "type", "button");
+ builder.AddAttribute(4, "onclick", EventCallback.Factory.Create(this, ExecuteTrigger));
+ }
- if (Busy)
+ if (IsBusy)
{
- builder.AddContent(3, BusyTemplate);
+ builder.AddContent(5, BusyTemplate);
}
else
{
- builder.AddContent(3, ChildContent);
+ builder.AddContent(6, ChildContent);
}
builder.CloseElement(); // button
}
+
///
protected override void OnParametersSet()
{
base.OnParametersSet();
- BusyTemplate ??= builder => builder.AddContent(0, "Busy...");
+ BusyTemplate ??= builder => {
+ builder.AddContent(0, BusyText);
+
+ builder.OpenElement(1, "span");
+ builder.AddAttribute(2, "aria-hidden", "true");
+ builder.AddAttribute(3, "class", "busy-loading-indicator");
+
+ builder.OpenElement(4, "span");
+ builder.AddAttribute(5, "class", "busy-loading-dot-1");
+ builder.CloseElement();
+
+ builder.OpenElement(6, "span");
+ builder.AddAttribute(7, "class", "busy-loading-dot-2");
+ builder.CloseElement();
+
+ builder.OpenElement(8, "span");
+ builder.AddAttribute(9, "class", "busy-loading-dot-3");
+ builder.CloseElement();
+
+ builder.CloseElement(); //span
+ };
+ }
+
+ protected bool IsBusy => Busy || Executing;
+
+ private async Task ExecuteTrigger()
+ {
+ if (!Trigger.HasDelegate)
+ return;
+
+ try
+ {
+ Executing = true;
+ await Trigger.InvokeAsync();
+ }
+ finally
+ {
+ Executing = false;
+ }
}
}
diff --git a/src/LoreSoft.Blazor.Controls/StateProvider.razor b/src/LoreSoft.Blazor.Controls/StateProvider.razor
new file mode 100644
index 00000000..21f0d494
--- /dev/null
+++ b/src/LoreSoft.Blazor.Controls/StateProvider.razor
@@ -0,0 +1,5 @@
+@typeparam TState
+
+
+ @ChildContent
+
diff --git a/src/LoreSoft.Blazor.Controls/StateProvider.razor.cs b/src/LoreSoft.Blazor.Controls/StateProvider.razor.cs
new file mode 100644
index 00000000..8eae1292
--- /dev/null
+++ b/src/LoreSoft.Blazor.Controls/StateProvider.razor.cs
@@ -0,0 +1,25 @@
+using Microsoft.AspNetCore.Components;
+
+namespace LoreSoft.Blazor.Controls;
+
+public partial class StateProvider
+{
+ [Parameter]
+ public required RenderFragment ChildContent { get; set; }
+
+ public event Action