Skip to content

Commit

Permalink
improve BusyButton, Add StateProvider, add ExpandTracker
Browse files Browse the repository at this point in the history
  • Loading branch information
pwelter34 committed Apr 12, 2024
1 parent 1059524 commit f6a9948
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 10 deletions.
2 changes: 0 additions & 2 deletions samples/Sample.ClientSide/Sample.ClientSide.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
<ImplicitUsings>enable</ImplicitUsings>

<IsPackable>false</IsPackable>

<BlazorCacheBootResources>false</BlazorCacheBootResources>
</PropertyGroup>

<ItemGroup>
Expand Down
20 changes: 17 additions & 3 deletions samples/Sample.Core/Pages/BusyButton/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

<div class="m-1">
<BusyButton Busy="@IsBusy"
BusyText="Saving"
Disabled="@IsDisabled"
id="save-button"
type="submit"
Expand All @@ -33,28 +34,41 @@
</BusyButton>
</div>



<div class="m-1">
<BusyButton Busy="@IsBusy"
Disabled="@IsDisabled"
id="save-button"
type="submit"
class="btn btn-primary">
<BusyTemplate>
Saving ...
<span class='spinner-border spinner-border-sm'></span> Saving...
</BusyTemplate>
<ChildContent>
Save
</ChildContent>
</BusyButton>
</div>


<div class="m-1">
<BusyButton Busy="@IsBusy"
Disabled="@IsDisabled"
Trigger="Process"
id="save-button"
class="btn btn-primary">
Process
</BusyButton>
</div>

@code {
[Parameter]
public bool IsBusy { get; set; } = true;

[Parameter]
public bool IsDisabled { get; set; } = false;

public async Task Process()
{
await Task.Delay(2000);
}
}
64 changes: 59 additions & 5 deletions src/LoreSoft.Blazor.Controls/BusyButton.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Web;

namespace LoreSoft.Blazor.Controls;

Expand All @@ -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; }

Expand All @@ -20,30 +24,80 @@ public class BusyButton : ComponentBase
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attributes { get; set; } = new Dictionary<string, object>();

[Parameter]
public EventCallback Trigger { get; set; }

private bool Executing { get; set; }

/// <inheritdoc />
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<MouseEventArgs>(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
}


/// <inheritdoc />
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;
}
}
}
5 changes: 5 additions & 0 deletions src/LoreSoft.Blazor.Controls/StateProvider.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@typeparam TState

<CascadingValue Value="this">
@ChildContent
</CascadingValue>
25 changes: 25 additions & 0 deletions src/LoreSoft.Blazor.Controls/StateProvider.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Components;

namespace LoreSoft.Blazor.Controls;

public partial class StateProvider<TState>
{
[Parameter]
public required RenderFragment ChildContent { get; set; }

public event Action<object> OnStateChange;

public TState? State { get; protected set; }

public virtual void Set(TState model)
{
State = model;
NotifyStateChanged(this);
}

public void NotifyStateChanged(object sender = null)
{
StateHasChanged();
OnStateChange?.Invoke(sender);
}
}
34 changes: 34 additions & 0 deletions src/LoreSoft.Blazor.Controls/Utilities/ExpandTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace LoreSoft.Blazor.Controls.Utilities;

public class ExpandTracker<TItem>
{
private readonly HashSet<TItem> _expandedItems = [];

public event Action OnChange;

public bool IsExpanded(TItem item)
{
return _expandedItems.Contains(item);
}

public void Toggle(TItem item)
{
if (_expandedItems.Contains(item))
_expandedItems.Remove(item);
else
_expandedItems.Add(item);

NotifyStateChanged();
}

public virtual void Clear()
{
_expandedItems.Clear();
NotifyStateChanged();
}

public void NotifyStateChanged()
{
OnChange?.Invoke();
}
}
44 changes: 44 additions & 0 deletions src/LoreSoft.Blazor.Controls/wwwroot/BlazorControls.css
Original file line number Diff line number Diff line change
Expand Up @@ -1022,4 +1022,48 @@ button.data-grid-header {

.loading-block-text {
color: #212529;
}

/* BusyButton */

.busy-loading-indicator {
align-self: center;
background-color: transparent;
border: 0;
box-sizing: border-box;
color: #ccc;
display: inline-block;
font-size: 4px;
line-height: 1;
margin-right: 4px;
outline: none;
padding: 8px;
text-align: center;
transition: color 150ms ease 0s;
vertical-align: middle
}

.busy-loading-dot-1, .busy-loading-dot-2, .busy-loading-dot-3 {
background-color: #ccc;
border-radius: 1em;
display: inline-block;
height: 1em;
vertical-align: top;
width: 1em
}

.busy-loading-dot-2, .busy-loading-dot-3 {
margin-left: 1em
}

.busy-loading-dot-1 {
animation: 1s ease-in-out 0ms infinite normal none running dot-loading
}

.busy-loading-dot-2 {
animation: 1s ease-in-out 160ms infinite normal none running dot-loading
}

.busy-loading-dot-3 {
animation: 1s ease-in-out 320ms infinite normal none running dot-loading
}

0 comments on commit f6a9948

Please sign in to comment.