4

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>
JYL
  • 8,228
  • 5
  • 39
  • 63
  • 3
    It's a *variable*, not a field. It doesn't exists outside the iteration (not the loop, the iteration). To keep track of that value you can make it a field/property of the items in `myList` and bind to it – Panagiotis Kanavos Oct 29 '21 at 15:29
  • 1
    The *theBool* variable only exists during the generating of your page. By the time you click on the element, it does not exist anymore! – XouDo Oct 29 '21 at 15:39
  • As theBool is captured by the lambda, I expected it still exists after le loop. @PanagiotisKanavos : Do you mean that Blazor only subscribe for Ui refresh on fields and not variables ? Do you know where is the documentation about that ? Can can't find any. Thx ! – JYL Oct 29 '21 at 15:42
  • 1
    @JYL why? The lambda itself ceases to exist once it's executed. And even it stayed alive somehow, the *variable* is declared inside the loop so its scope is only the iteration – Panagiotis Kanavos Oct 29 '21 at 15:43
  • 2
    @PanagiotisKanavos The scope is inside the loop, but the lifetime can extend beyond the loop. That's the whole point of closures. Now that doesn't make it extend to other applications, but it can be, and is, extended beyond the scope of the loop. – Servy Oct 29 '21 at 15:51
  • When I said that theBool is expected to be captured by the lambda, I'm following this answer : https://stackoverflow.com/a/54813295/218873 (see "localVariable"). – JYL Oct 29 '21 at 15:57
  • @JYL Yes, but the variable is resolved to its value when the page response is sent to the client. The variable doesn't persist beyond the lifetime of the server's response rendering time into subsequent page loads or into a client side variable. The variable lives *until the point at which you write out the HTML*. – Servy Oct 29 '21 at 16:09
  • @Servy the question is about Blazor WASM, so it's executed on the client. While `@theBool` is captured in the event handler lambda, `For @item, theBool is @theBool` was rendered when the loop run and won't be re-executed in response to the event. That would require a call to `StateHasChanged` but even that would result in executing the entire loop, including `var theBool = false;` – Panagiotis Kanavos Oct 29 '21 at 16:16
  • @JYL what are you trying to do in the first place? If you want to modify a field locally you can use a component with a boolean field – Panagiotis Kanavos Oct 29 '21 at 16:18
  • @PanagiotisKanavos : that makes sens, thanks ! As you said, the key here is "_that would result in executing the entire loop_". That's what happen when I click the link, I added a `Console.WriteLine` before the `
  • ` to prove it. What I'm trying to achieve is to reverse the bool parameter of a component added inside the loop. I'll complete my code sample.
  • – JYL Oct 29 '21 at 16:29
  • @PanagiotisKanavos : I've updated my question. – JYL Oct 29 '21 at 16:36
  • Foreach is doing its thing every time there is a change on the page (some variable is changed) . And you set thebool to false every time. – Alamakanambra Oct 29 '21 at 17:11