Declined
Last Updated: 08 Nov 2019 12:44 by ADMIN
Portia
Created on: 31 Oct 2019 22:04
Category: UI for Blazor
Type: Bug Report
0
Multiple Tabs with Same Component - OnInitialized Only Running for 1st Instance?

When I create multiple tabs and each tab has the same type of component, the OnInitialized is only running for the first one I click on.  

Here is a simplified example to demonstrate:

MAIN PAGE:

@page "/tabtest"
@using Telerik.Blazor.Components

<div>Product XYZ</div>

<TelerikTabStrip TabPosition="Telerik.Blazor.TabPosition.Top" @ref="productTabStrip" @bind-ActiveTabIndex="@ActiveTabIndex">
    <TabStripTab Title="Details">
        <div class="container sms-tab-content">
            GENERAL PRODUCT INTRO STUFF HERE
        </div>
    </TabStripTab>

    @foreach (var item in listOfWidgets)
    {
        <TabStripTab Title="@item.WidgetName" Disabled="false">
            <Widget WidgetID="@item.WidgetID" WidgetName="@item.WidgetName" />
        </TabStripTab>
    }

</TelerikTabStrip>

<div style="margin-top: 15px;">
    <div><b>Below is a flat non-tab example of repeating widgets:</b></div>
    @foreach (var item in listOfWidgets)
    {        
        <Widget WidgetID="@item.WidgetID" WidgetName="@item.WidgetName" />        
    }
</div>


@code {

    Telerik.Blazor.Components.TelerikTabStrip productTabStrip;

    public int ActiveTabIndex { get; set; } = 0;

    protected class Widget
    {
        public int WidgetID { get; set; }
        public string WidgetName { get; set; }
    }

    private List<Widget> listOfWidgets = new List<Widget>();

    protected void GetData()
    {
        listOfWidgets.Add(new Widget { WidgetID = 1, WidgetName = "Cog" });
        listOfWidgets.Add(new Widget { WidgetID = 2, WidgetName = "Wheel" });
        listOfWidgets.Add(new Widget { WidgetID = 3, WidgetName = "Bloof" });
    }

    protected override void OnInitialized()
    {
        GetData();
    }

}    

 

WIDGET COMPONENT:

@page "/widget/{WidgetID:int}/{WidgetName}"

<div>
    <div>@WidgetID</div>
    <div>@WidgetName</div>
    <div>@ExtraWidgetInfo</div>
</div>

@code {


    [Parameter] public int WidgetID { get; set; } = 0;
    [Parameter] public string WidgetName { get; set; } = "Nothing";

    private string ExtraWidgetInfo { get; set; } = "Stuff";

    protected override void OnInitialized()
    {
        if (WidgetName == "Cog")
            ExtraWidgetInfo = "This is good info about cogs.";
        if (WidgetName == "Wheel")
            ExtraWidgetInfo = "This is good info about wheels.";
        if (WidgetName == "Bloof")
            ExtraWidgetInfo = "This is good info about bloofs.";
    }

}
Attached Files:
3 comments
Portia
Posted on: 07 Nov 2019 23:56
Thank you for the explanation, using @key now and everything is working fine.
ADMIN
Marin Bratanov
Posted on: 07 Nov 2019 15:36

Hello Portia,

Here's what happens in this case:

  1. The first instance of the Widget component is rendered. Its OnInitialized fires.
  2. The next time an instance is shown, it only gets new parameters because the framework detects that the same component is rendering in the same place - the tab strip has only one content area.

So, this behavior is expected, and I have documented it (link to the commit).

The solution is to use the @key feature of the framework, like this:

 

    @foreach (var item in listOfWidgets)
    {
        <TabStripTab Title="@item.WidgetName" Disabled="false">
            <Widget @key="@item.WidgetID" WidgetID="@item.WidgetID" WidgetName="@item.WidgetName" />
        </TabStripTab>
    }

 

 

Regards,
Marin Bratanov
Progress Telerik

 UI for Blazor
ADMIN
Marin Bratanov
Posted on: 01 Nov 2019 06:54

Hi Portia,

I am logging this for review. In the meantime, you can try the following workaround - using the OnParameteraSet event instead:

 

@page "/widget/{WidgetID:int}/{WidgetName}"

<div>
    <div>@WidgetID</div>
    <div>@WidgetName</div>
    <div>@ExtraWidgetInfo</div>
</div>

@code {
    [Parameter] public int WidgetID { get; set; } = 0;
    [Parameter] public string WidgetName { get; set; } = "Nothing";

    private string ExtraWidgetInfo { get; set; } = "Stuff";

    protected override void OnParametersSet()
    {
         if (WidgetName == "Cog")
            ExtraWidgetInfo = "This is good info about cogs.";
        if (WidgetName == "Wheel")
            ExtraWidgetInfo = "This is good info about wheels.";
        if (WidgetName == "Bloof")
            ExtraWidgetInfo = "This is good info about bloofs.";
    }

    protected override void OnInitialized()
    {
       
    }
}

 

 

 

Regards,
Marin Bratanov
Progress Telerik

 UI for Blazor