Reputation: 1816
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:
<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; } }
<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:
but when I entered the second one, all of them are replaced for the last one:
Any idea whats going on?
Upvotes: 6
Views: 16438
Reputation: 5218
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.
Upvotes: 0
Reputation: 8932
You are making it too complicated. You don't need to dynamically instantiate components for this scenario to work.
You can just do a:
<ul>
@foreach (var item in listItems)
{
<myComponent bind-myVar="@item"></myComponent>
}
</ul>
And the components will be instantiated for you.
Also see here how to make the parameters work on your component.
Upvotes: 5