AskYous
AskYous

Reputation: 4740

Tabs with OnInitializedAsync?

Consider the following requirements:

But here is where the challenge comes in:

How is this possible in blazor?

Proposed Solution: Use @if to decide if each tab should render

Code:

<ul class="nav nav-tabs">
    <li class="nav-item">
        <a class="nav-link" @onclick="() => tabId == 1">Tab 1</a>
    </li>
    <li class="nav-item">
        <a class="nav-link" @onclick="() => tabId == 2">Tab 2</a>
    </li>
    <li class="nav-item">
        <a class="nav-link" @onclick="() => tabId == 3">Tab 3</a>
    </li>
</ul>

@switch(tabId) 
{
    case 1:
        <Tab1Component />
        break;
    case 2:
        <Tab2Component />
        break;
    case 3:
        <Tab3Component />
        break;
}

@code {
    private int tabId = 1;
}

But this does not work since when I switch tabs, OnInitializedAsync gets called every time.

What would be helpful is if there is a hidden blazor attribute where I can just add an attribute to the tab bodies like this:

<Tab1Component @hidden="tabId != 1" />

Upvotes: 1

Views: 1227

Answers (2)

AskYous
AskYous

Reputation: 4740

One solution I found was to create a Hidable component:

Hidable.razor.cs

public partial class Hidable
{
    [Parameter] public bool? hidden { get; set; }
    [Parameter] public bool? show { get; set; }
    protected override void OnParametersSet()
    {
        if (hidden.HasValue && show.HasValue)
        {
            throw new Exception($"Do not set BOTH {nameof(hidden)} and {nameof(show)}!");
        }
    }
    [Parameter] public RenderFragment ChildContent { get; set; }
    private string style
    {
        get
        {
            if (hidden.HasValue && !hidden.Value) return "";
            if (show.HasValue && show.Value) return "";
            return "display: none";
        }
    }
}

Hidable.razor

<div style="@style">@ChildContent</div>

Example use:

<Hidable hidden="@(tabId == 1)">
    <Tab1Component />
</Hidable>
<Hidable hidden="@(tabId == 2)">
    <Tab2Component />
</Hidable>
<Hidable hidden="@(tabId == 3)">
    <Tab3Component />
</Hidable>

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273621

  • A tab body should not be initialized twice when it re-appears. (It should not run OnInitializedAsync twice).

Blazor determnines when a Component is Initialized, your problem is actually "how to maintain state". Many ways to do that.

But I can see that a complex control with user input would be hard to restore.

What would be helpful is if there is a hidden blazor attribute

You could make one. Your Tab1-3Component classes can expose a boolean and use CSS to set dispplay=none on the outer tag. I suppose you can't conditiopnaslly render because that would lose state again.

The switch statement would be replaced by

<Tab1Component Visible=(tabId==1) />
<Tab2Component Visible=(tabId==2) />
<Tab3Component Visible=(tabId==3) />

Upvotes: 3

Related Questions