add list of dynamic components in blazor

asp.net-core blazor c#

Question

I just started to have a look in blazor (v0.3) and doing some test I wanted to add a list using blazor

First I created a List<string> to test a simple list in the same page

<ul>
    @foreach (var item in listItems)
    {
        <li>@item</li>
    }
</ul>


@functions {

    private List<string> listItems = new List<string>();
    private string newItem;

    private void AddItem()
    {
        if (string.IsNullOrEmpty(newItem))
            return;

        listItems.Add(newItem);
        newItem = "";
    }

}

this is working fine, is adding every element to the list when I add it. but then, i tried to add components, add a single component was easy, based on this question here but for a list I had the next problem:

  • I created a <li> compontent just to test the functionality of components, here is the component view
<li id="@ID">
    @Text
</li>   




@functions {
  [Parameter]
  string Text { get; set; } 
  [Parameter]
  string ID { get; set; }
}
  • then in the parent view
<input type="text" bind="TxtExample" name="inpAdd"/>
  <button onclick="@addCompoment">add comp1</button>
<div class="simple-list-list">
    @if (!componentListTest.Any())
    {
        <p>You have no items in your list</p>
    }
    else
    {
        <ul>
            @foreach (var item in componentListTest)
            {
                @item
            }
        </ul>
    }
</div>

@functions {

    private List<RenderFragment> componentListTest { get; set; }
    private int currentCount {get; set;}
    private string TxtExample { get; set; }

    protected override void OnInit()
    {
        currentCount = 0;
        componentListTest = new List<RenderFragment>();
    }


    protected void addCompoment()
    {

        componentListTest.Add(CreateDynamicComponent(currentCount));
        currentCount++;
    }


    RenderFragment CreateDynamicComponent(int counter) => builder =>
    {
        var seq = 0;
        builder.OpenComponent(seq, typeof(listExample));
        builder.AddAttribute(++seq, "Text", "text --  "+TxtExample);
        builder.AddAttribute(++seq, "id","listed-"+counter);

        builder.CloseComponent();

    };
}

when I load the fist element is loaded correctly: enter image description here

but when I entered the second one, all of them are replaced for the last one:

enter image description here

Any idea whats going on?

Popular Answer

This is because TxtExample is global to the component. When Blazor detects a potential UI change, it recalculates the entire component and updates the DOM with any differences. So when you change the textbox, TxtExample is updated and then the Razor is recalculating, inserting the new value of TxtExample for all rows.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why