Why does @for loop does not work in Razor and Blazor?

Viewed 656

This code works:

@page "/"
<button @onclick="@(()=>fun(0))" style="color: @style1[0]">
    Click me
</button>
<button @onclick="@(()=>fun(1))" style="color: @style1[1]">
    Click me
</button>
<button @onclick="@(()=>fun(2))" style="color: @style1[2]">
    Click me
</button>

@code{
    List<string> style1 = new List<string> { "black" , "black", "black" };
    void fun(int m)
    {
       try
       {
           if (style1[m] == "black") style1[m] = "red";
               else style1[m] = "black";
       }
       catch
       {
            Console.WriteLine("m = {0}", m);
       }
    }
}

But this one does not:

@page "/"
@for (int i = 0; i < 3; i++)
{
    <button @onclick="@(()=>fun(i))" style="color: @style1[i]">
        Click me
    </button>
}
@code{
//same as above
}

and this is the error in Console (without try-catch):

Unhandled exception rendering component: Index was out of range. Must be non-negative and less than the size of the collection.

after try-catch:

m = 3

Thanks

1 Answers

Take a look at the following code (a simpler version of your code in my index.razor)

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@for (int i = 0; i < 3; i++)
{
    <button class="btn btn-primary mr-2" @onclick="(() => ButtonClick(i))">@($"Button {i}") </button>
}
<h4>Value = @value</h4>

@code {

    int value = -1;

    void ButtonClick(int x)
        => value = x;
}

Your expectation is that Value will display 1 when you click on Button 1. Not so, it always displays 3, the final value of i. The button click event submits the value of i when the button is clicked, the loop has long completed.

In your code i is 3 - the last version of i that stopped the for loop. - and m in style1[m] is 3 pointing to a none existent 4th member of style1. Index was out of range is quite correct, but quite as informative as it could be.

Sometimes you can't see the wood for the trees!!

Related