Home > Back-end >  How to change a variable declared inside a loop?
How to change a variable declared inside a loop?

Time:10-30

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 : List of items

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.

  • Related