Tabs control for Blazor

blazor tabs control

In this new post, I explain how to create and use Tabs control for Blazor Web Assembly and Blazor Server. You have the full code of this component on GitHub.

As I explained in my previous post Segment Control For Blazor, the first thing I have to do is to creating 2 new Razor Class Library in Visual Studio and named them as Tabs and Tab.

Definition of Tab

First, we have to define a child of the Tabs container. In one Razor Class Library, change the name to Tab.razor.

@if (Parent.ActivePage == this)
{
    @ChildContent
}

@code {
    [CascadingParameter]
    private Tabs Parent { get; set; }

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

    [Parameter]
    public string Text { get; set; }

    [Parameter]
    public string Value { get; set; }

    [Parameter]
    public bool Enabled { get; set; } = true;

    protected override void OnInitialized()
    {
        if (Parent == null)
            throw new ArgumentNullException(nameof(Parent), 
                "TabPage must exist within a TabControl");

        base.OnInitialized();
        Parent.AddPage(this);
    }
}

So, when I define a new Tab I should pass those parameters:

  • Text is the label you want to show to the user
  • Value is the real value you want to use
  • Enabled allows the user to click on this tab or not

Then, the OnInitialized() checks if there is a parent and add this tab to the list present in the tabs container. If this tab is the active one, the component shows the content.

Tabs container

So, the Tabs container contains all the tabs to display.

<CascadingValue Value="this">
    <div class="tabs">
        <div class="tab-container">
            <div class="tab-filling tab-filling-left">
                @((MarkupString)TextFilling1)
            </div>
            @foreach (Tab tabPage in Pages)
            {
                <div class="tab @GetTabCSS(tabPage)" @onclick=@( () => ActivatePage(tabPage) )>
                    @tabPage.Text
                </div>
            }
            <div class="tab-filling tab-filling-right">
                @((MarkupString)TextFilling2)
            </div>
        </div>
        <div class="tab-content">
            @ChildContent
        </div>
    </div>
</CascadingValue>

Now, I have to add the code to the page.

@code {
    [Parameter] public string TextFilling1 { get; set; }
    [Parameter] public string TextFilling2 { get; set; }
    [Parameter] public RenderFragment ChildContent { get; set; }

    [Parameter] public EventCallback<Tab> OnTabChanged { get; set; }

    public Tab ActivePage { get; set; }
    List<Tab> Pages = new List<Tab>();

    internal void AddPage(Tab tabPage)
    {
        Pages.Add(tabPage);
        if (Pages.Count == 1)
            ActivePage = tabPage;

        StateHasChanged();
    }

    string GetTabCSS(Tab page)
    {
        if (!page.Enabled)
            return "tab-disabled";

        return page == ActivePage ? "tab-active" : "";
    }

    void ActivatePage(Tab page)
    {
        if (page.Enabled)
        {
            ActivePage = page;
            OnTabChanged.InvokeAsync(page);
        }
    }
}

So, in the next section I show all the attributes and events we can use.

Anatomy of Tabs

Tabs container attributes

Anatomy of Tabs control for Blazor - Tabs control for Blazor
Anatomy of Tabs control for Blazor
AttributeDescription
TextFilling1This text is displayed on the left hand side of the tabs
TextFilling2This text is displayed on the right hand side of the tabs

Tabs container events

Also, Tabs has the following events that you can use.

EventDescription
OnTabChangedWhen the use click on a new tab, this event is raised. So, you can attach a function to read the new tab object

Tab attributes

AttributeDescription
TextThe text to display in the tab
ValueThe value associate to a tab (useful if you have to filter your data)
EnabledIs this tab enabled? If not the user can’t click on it. By default is True

How to use it?

First, add the NuGet package in your project. The name of the package is PSC.Blazor.Components.Tabs and the only dependency it has is Microsoft.AspNetCore.Components.Web (>= 5.0.10).

After that, in your wwwroot\index.html or in the hosts file, you have to add a theme (CSS) for your segment control. Obviously, you can create your own theme. So, use this code:

<link href="_content/PSC.Blazor.Components.Tabs/themes/{theme-name}.css" rel="stylesheet" />

Example

<Tabs TextFilling1="@text1" TextFilling2="@text2" OnTabChanged="OnTabChanged">
    <Tab Text="Tab 1" Value="Tab1">
        <h2>Content Tab 1</h2>
        <p>
            This is the content for the Tab 1. It is enabled.
        </p>
    </Tab>
    <Tab Text="Tab 2" Value="Tab2">
        <h2>Content Tab 2</h2>
        <p>
            This is the content for the Tab 2. It is enabled.
        </p>
    </Tab>
    <Tab Text="Tab 3" Value="Tab3">
        <h2>Content Tab 3</h2>
        <p>
            This is the content for the Tab 3. It is enabled.
        </p>
    </Tab>
    <Tab Text="Tab 4" Enabled="@IsEnabled" Value="Tab4">
        <h2>Content Tab 4</h2>
        <p>
            This is the content for the Tab 4. It is disabled if <i>IsEnabled = false</i>
        </p>
    </Tab>
</Tabs>

@code {
    public string text1 = "Text on the left";
    public string text2 = "Text on the right";

    public bool IsEnabled = false;

    public async Task OnTabChanged(Tab tab)
    {
        text1 = $"Tab value: {tab.Value}";
        text2 = $"Tab text: {tab.Text}";
    }
}

Themes

Blue

Blue theme - Tabs control for Blazor
Blue theme

Green

Green theme - Tabs control for Blazor
Green theme
Light colors theme - Tabs control for Blazor
Light colors theme

Red

Red theme
Red theme

Wrap up

So, now we have a nice and simple Tabs control for Blazor to use in our projects. If you have any comment please add it at the bottom of this post or use the Forum.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.