Consider the following code :
In MyPage.razor :
<ul>
@foreach (var item in myList)
{
var theBool = false;
<li>
<span>For @item, theBool is @theBool</span>
(<a href="" @onclick="@(e => theBool = !theBool)">Reverse bool for @item</a>)
</li>
}
</ul>
@code {
List<string> myList = new() { "item1", "item2", "item3", "item4", "item5", };
}
... which produce the following output :
I expect that clicking on a link will switch the preceding bool value, so it shows "True" instead of "False". It's not working at all, the variable seems to be changed but the UI (the <span>
) is not refreshed. What is the good way to implement this in Blazor Webassembly ?
(I hope not to be forced to use the @code
section : it would be a major code overhead in term of maintainability).
UPDATE 1
This is what I'm trying to achieve : A click on a link (which is outside of a component) has to change the parameter of the component (to change the component behavior) :
<ul>
@foreach (var item in myList)
{
var theBool = false;
<li>
<a href="" @onclick="@(e => theBool = !theBool)">Show/Hide details</a>
<MyCoolComponent DisplayDetails="@theBool"></MyCoolComponent>
</li>
}
</ul>
CodePudding user response:
The boolean value is getting lost with each iteration. Use a dictionary instead of list to store the values together.
The key is the string and the value is the boolean:
<ul>
@foreach (var item in myList)
{
<li>
<span>For @item.Key, theBool is @item.Value</span>
(<a href="" @onclick="@(() => myList[item.Key] = !myList[item.Key])">
Reverse bool for @item.Key
</a>)
</li>
}
</ul>
@code {
Dictionary<string, bool> myList = new()
{
{"item1", false},
{"item2", false},
{"item3", false},
{"item4", false},
{"item5", false}
};
}
When you update the boolean via click, the value will be stored with its key.
CodePudding user response:
Your code will never work as at each iteration of the loop the local variable theBool is set to false; that is you can't see the changes on the UI...
You can solve it like this:
<ul>
@foreach (var item in Items)
{
<li>
<span>For @item.Name, item.IsSelected is @item.IsSelected</span>
(<a href="" @onclick="@(e => { item.IsSelected = !item.IsSelected; })">Reverse bool for @item.Name</a>)
</li>
}
</ul>
@code {
private List<Item> Items = Enumerable.Range(1, 5).Select(i => new Item { Name = $"item{i}" }).ToList();
public class Item
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
}
Copy and test...
CodePudding user response:
Not an answer, I'll remove it soon:
As theBool is captured by the lambda, I expected it still exists after le loop.
That is true...
@PanagiotisKanavos : Do you mean that Blazor only subscribe for Ui refresh on fields and not variables ?
Each time you click on an anchor element, the StateHasChanged method is automatically called by the framework, and the UI is re-rendered, but you can't see it changed, as at the start of the loop you've got var theBool = false;
And thus, <span>For @item, theBool is @theBool</span>
is re-rendered to:
<span>For item2, theBool is false</span>
if you've clicked on the second item.