Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🆕 feat(Tabs): re-render slider when a tab is removed(unregister) #605

Merged
merged 4 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,11 @@ private async Task<bool> UpdateActiveForRoutable()
if (matched && ItemGroup is not null && !isActive)
{
await ItemGroup.ToggleAsync(Value);
await OnActiveUpdatedForRoutable();
}

return isActive != matched;
}

protected virtual Task OnActiveUpdatedForRoutable() => Task.CompletedTask;

protected override ValueTask DisposeAsyncCore()
{
NavigationManager.LocationChanged -= OnLocationChanged;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,14 @@ private void RefreshItemsState()
Items.ForEach(item => item.RefreshState());
}

public virtual void Register(IGroupable item)
protected virtual StringNumber InitDefaultItemValue()
{
item.Value ??= _registeredItemsIndex++;
return _registeredItemsIndex++;
}

internal virtual void Register(IGroupable item)
{
item.Value ??= InitDefaultItemValue();

Items.Add(item);

Expand Down Expand Up @@ -109,7 +114,11 @@ public virtual void Register(IGroupable item)
public virtual void Unregister(IGroupable item)
{
Items.Remove(item);
_registeredItemsIndex--;

if (_registeredItemsIndex > 0)
{
_registeredItemsIndex--;
}
}

private async Task UpdateMandatoryAsync(bool last = false)
Expand Down
7 changes: 0 additions & 7 deletions src/Component/BlazorComponent/Components/Tabs/BTab.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ public BTab() : base(GroupType.SlideGroup)

protected override bool IsRoutable => Href != null && HasRoutableAncestor;

protected override async Task OnActiveUpdatedForRoutable()
{
if (Tabs == null) return;

await Tabs.CallSlider();
}

protected override bool AfterHandleEventShouldRender() => false;

private async Task HandleOnClick(MouseEventArgs args)
Expand Down
67 changes: 50 additions & 17 deletions src/Component/BlazorComponent/Components/Tabs/BTabs.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public EventCallback<StringNumber> ValueChanged

private StringNumber? _prevValue;
private int _registeredTabItemsIndex;
private bool _callSliderOnAfterRender;
private CancellationTokenSource? _callSliderCts;

private List<ITabItem> TabItems { get; set; } = new();

Expand Down Expand Up @@ -98,20 +100,25 @@ public bool IsDark
}

List<ITabItem> ITabs.TabItems => TabItems;

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

if (firstRender)
{
await ResizeJSModule.ObserverAsync(Ref, OnResize);

await CallSlider();
_callSliderOnAfterRender = true;
}
else if (_prevValue != Value)
{
_prevValue = Value;
_callSliderOnAfterRender = true;
}

if (_callSliderOnAfterRender)
{
_callSliderOnAfterRender = false;
await CallSlider();
}
}
Expand All @@ -134,28 +141,45 @@ public void UnregisterTabItem(ITabItem tabItem)
TabItems.Remove(tabItem);
}

/// <summary>
/// Re-render slider immediately. For the case of deleting tabs,
/// it is recommended to use <see cref="CallSliderAfterRender"/>.
/// </summary>
[MasaApiPublicMethod]
public async Task CallSlider()
{
if (HideSlider) return;

var item = Instance?.Items?.FirstOrDefault(item => item.Value == Instance.Value);
if (item?.Ref.Context == null)
{
Slider = (0, 0, 0, 0, 0);
}
else
_callSliderCts?.Cancel();
_callSliderCts = new();

try
{
var el = await JsInvokeAsync<Web.Element>(JsInteropConstants.GetDomInfo, item.Ref);
var height = !Vertical ? SliderSize.TryGetNumber().number : el.ScrollHeight;
var left = Vertical ? 0 : el.OffsetLeft;
var right = Vertical ? 0 : el.OffsetLeft + el.OffsetWidth;
var top = el.OffsetTop;
await Task.Delay(16, _callSliderCts.Token);

var item = Instance?.Items?.FirstOrDefault(item => item.Value == Instance.Value);
if (item?.Ref.Context == null)
{
Slider = (0, 0, 0, 0, 0);
}
else
{
var el = await JsInvokeAsync<Web.Element>(JsInteropConstants.GetDomInfo, item.Ref);
var height = !Vertical ? SliderSize.TryGetNumber().number : el.ScrollHeight;
var left = Vertical ? 0 : el.OffsetLeft;
var right = Vertical ? 0 : el.OffsetLeft + el.OffsetWidth;
var top = el.OffsetTop;
var width = Vertical ? SliderSize.TryGetNumber().number : el.ClientWidth; // REVIEW: el.ScrollWidth was used in Vuetify2

Slider = (height, left, right, top, width);
}
Slider = (height, left, right, top, width);
}

StateHasChanged();
StateHasChanged();
}
catch (TaskCanceledException)
{
// ignored
}
}

private async Task OnResize()
Expand All @@ -168,6 +192,15 @@ private async Task OnResize()
await CallSlider();
}

/// <summary>
/// Re-render slider in <see cref="OnAfterRenderAsync"/>
/// </summary>
[MasaApiPublicMethod]
public void CallSliderAfterRender()
{
_callSliderOnAfterRender = true;
}

protected override async ValueTask DisposeAsyncCore()
{
await ResizeJSModule.UnobserveAsync(Ref);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ protected override void RegisterWatchers(PropertyWatcher watcher)
true);
}

public override void Register(IGroupable item)
internal override void Register(IGroupable item)
{
base.Register(item);

Expand Down
Loading