Skip to content

Commit

Permalink
🐛 (ExpansionPanels): unexpected IsActive paramter; ActiveClass is not…
Browse files Browse the repository at this point in the history
… working (#2142)
  • Loading branch information
capdiem authored Sep 9, 2024
1 parent 6304daf commit 5ee3633
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 201 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@namespace Masa.Blazor
@inherits MGroupItem<MExpansionPanels>
@inherits Masa.Blazor.Components.ItemGroup.MGroupableBase<MExpansionPanels>

<CascadingValue Value="this" IsFixed>
<div class="@GetClass()"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace Masa.Blazor;
using Masa.Blazor.Components.ItemGroup;

public partial class MExpansionPanel : MGroupItem<MExpansionPanels>
namespace Masa.Blazor;

public partial class MExpansionPanel : MGroupableBase<MExpansionPanels>
{
public MExpansionPanel() : base(GroupType.ExpansionPanels, true)
{
Expand All @@ -15,7 +17,10 @@ public MExpansionPanel() : base(GroupType.ExpansionPanels, true)
[Parameter]
[MasaApiParameter(ReleasedOn = "v1.6.0")]
public string? Text { get; set; }


[Parameter]
public RenderFragment? ChildContent { get; set; }

public bool NextActive => ItemGroup != null && ItemGroup.NextActiveKeys.Contains(Value);

public bool IsDisabled => ItemGroup != null && (ItemGroup.Disabled || Disabled);
Expand All @@ -32,13 +37,6 @@ public async Task Toggle()
private static Block _block = new("m-expansion-panel");
private ModifierBuilder _modifierBuilder = _block.CreateModifierBuilder();

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

ActiveClass ??= "m-item--active";
}

protected override IEnumerable<string> BuildComponentClass()
{
yield return _modifierBuilder
Expand Down
1 change: 0 additions & 1 deletion src/Masa.Blazor/Components/ItemGroup/MGroupItem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Masa.Blazor.Components.ItemGroup;
using Masa.Blazor.Mixins;

namespace Masa.Blazor;

Expand Down
200 changes: 12 additions & 188 deletions src/Masa.Blazor/Components/ItemGroup/MGroupable.cs
Original file line number Diff line number Diff line change
@@ -1,201 +1,25 @@
namespace Masa.Blazor.Components.ItemGroup;

public abstract class MGroupable<TGroup> : MasaComponentBase, IGroupable
/// <summary>
/// The base class for groupable components.
/// The active state can be controlled by its parent group component or IsActive property.
/// </summary>
/// <typeparam name="TGroup"></typeparam>
public abstract class MGroupable<TGroup> : MGroupableBase<TGroup>, IGroupable
where TGroup : MItemGroupBase
{
[CascadingParameter]
public TGroup? ItemGroup { get; set; }

[Parameter]
public string? ActiveClass { get; set; }

[Parameter]
public virtual bool Disabled { get; set; }

// TODO: use Value instead of IsActive
[Parameter]
public bool IsActive
{
get => _isActive ?? false;
set => _isActive = value;
}

[Parameter]
public StringNumber? Value
{
get => _value;
set
{
if (value == null) return;

_value = value;
}
}

/// <summary>
/// whether to enable bootable.
/// </summary>
private readonly bool _bootable;

/// <summary>
/// the <see cref="GroupType"/> of the groupable component.
/// </summary>
private readonly GroupType _groupType;

private bool? _isActive;
private StringNumber? _value;
private bool _firstRenderAfterBooting;

/// <summary>
/// Initializes a base component <see cref="MGroupable{TGroup}"/> with the <see cref="GroupType"/>.
/// </summary>
/// <param name="groupType">the <see cref="GroupType"/> of the groupable component.</param>
protected MGroupable(GroupType groupType)
{
_groupType = groupType;
}

/// <summary>
/// Initializes a base component <see cref="MGroupable{TGroup}"/> with the <see cref="GroupType"/>
/// and specifies whether to bootable.
/// </summary>
/// <param name="groupType">the <see cref="GroupType"/> of the groupable component.</param>
/// <param name="bootable">determines whether bootable is enabled or not.</param>
protected MGroupable(GroupType groupType, bool bootable) : this(groupType)
{
_bootable = bootable;
}

protected string? ComputedActiveClass => ActiveClass ?? ItemGroup?.ActiveClass;

/// <summary>
/// Determines whether the component has a routable ancestor component.
/// </summary>
protected virtual bool HasRoutableAncestor => ItemGroup is IAncestorRoutable { Routable: true };

/// <summary>
/// The routable ancestor.
/// </summary>
protected IAncestorRoutable? RoutableAncestor => HasRoutableAncestor ? (IAncestorRoutable)ItemGroup! : null;

protected bool Matched => ItemGroup != null && (ItemGroup.GroupType == _groupType);

protected bool ValueMatched => Matched && ItemGroup!.InternalValues.Contains(Value);

public bool InternalIsActive { get; private set; }

/// <summary>
/// Determines whether the component has been booted.
/// </summary>
protected bool IsBooted { get; private set; }

protected virtual bool IsEager { get; } = false;

protected virtual bool HasTransition { get; } = false;

protected override async Task OnInitializedAsync()
protected MGroupable(GroupType groupType) : base(groupType)
{
if (!Matched) return;

if (this is IGroupable item)
{
await ItemGroup!.Register(item);
}

await base.OnInitializedAsync();
}

protected override async Task OnParametersSetAsync()
protected MGroupable(GroupType groupType, bool bootable) : base(groupType, bootable)
{
if (_isActive.HasValue) // if setting by [Parameter]IsActive, Matched is not required.
{
await SetInternalIsActive(_isActive.Value);
}
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);

if (_firstRenderAfterBooting)
{
await Task.Delay(16);
_firstRenderAfterBooting = false;

InternalIsActive = true;
StateHasChanged();
}
}

public async Task RefreshState()
{
if (!Matched || HasRoutableAncestor) return;

await SetInternalIsActive(ValueMatched);
}

protected async Task ToggleAsync()
{
if (!Matched) return;

await ItemGroup!.ToggleAsync(Value);
}

protected async Task SetInternalIsActive(bool val, bool force = false)
{
if (IsEager)
{
if (InternalIsActive != val || force)
{
InternalIsActive = val;
StateHasChanged();
}
}
else
{
if (!IsBooted)
{
if (val)
{
IsBooted = true;

if (HasTransition)
{
_firstRenderAfterBooting = true;

await Task.Delay(16);
}
else
{
InternalIsActive = true;
}

StateHasChanged();
}
}
else if (InternalIsActive != val || force)
{
if (_firstRenderAfterBooting)
{
// waiting for one frame(16ms) to make sure the element has been rendered,
// and then set the InternalIsActive to be true to invoke transition.
await Task.Delay(16);
_firstRenderAfterBooting = false;
}

InternalIsActive = val;
StateHasChanged();
}
}
}

protected override async ValueTask DisposeAsyncCore()
[Parameter]
public bool IsActive
{
if (Matched && this is IGroupable item)
{
ItemGroup!.Unregister(item);
}

await base.DisposeAsyncCore();
get => UserActive ?? false;
set => UserActive = value;
}
}
Loading

0 comments on commit 5ee3633

Please sign in to comment.