Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor binding wrong value in for loop #22302

Closed
water1st opened this issue May 28, 2020 · 1 comment
Closed

Blazor binding wrong value in for loop #22302

water1st opened this issue May 28, 2020 · 1 comment
Labels
area-blazor Includes: Blazor, Razor Components

Comments

@water1st
Copy link

water1st commented May 28, 2020

Describe the bug

Using variables of for loop to bind a value in for loop body, such as i, will bind all binding values to the values of termination conditions of for loop (step count +1)

To Reproduce

step1:create the webassembly blazor default demo
step2:modify the FetchData.razor just like this

@using TEST.DTO
@using System.Net.Http
@page "/fetchdata"
@inject IHttpClientFactory clientFactory

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
                <th>Operation</th>
            </tr>
        </thead>
        <tbody>
            @for (int i = 0; i < forecasts.Count; i++)
            {
                var forecast = forecasts[i];
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                    <td><button @onclick="@(e => forecasts.RemoveAt(i))">Remove</button></td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private IList<WeatherForecast> forecasts;

    protected override async Task OnInitializedAsync()
    {
        var httpClient = clientFactory.CreateClient("Test");
        forecasts = await httpClient.GetFromJsonAsync<List<WeatherForecast>>("weatherforecast");
    }
}

step3: register HttpClientFactory to ServiceCollection
setp4: run server
step5: run blazor and click the remove button

Further technical details

If I define a variable "index" and assign the value of "i" to "index" in the for loop body, binding "index" it's work good

        <tbody>
            @for (int i = 0; i < forecasts.Count; i++)
            {
                var index = i;
                var forecast = forecasts[index];
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                    <td><button @onclick="@(e => forecasts.RemoveAt(index))">Remove</button></td>
                </tr>
            }
        </tbody>
  • ASP.NET Core version : 3.1.300
  • Include the output of :
C:\Users\MyUserName>dotnet --info
.NET Core SDK(反映任何 global.json):
Version: 3.1.300
Commit: b2475c1295

运行时环境:
OS Name: Windows
OS Version: 10.0.18363
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.1.300\

Host (useful for support):
Version: 3.1.4
Commit: 0c2e69caa6

.NET Core SDKs installed:
2.1.701 [C:\Program Files\dotnet\sdk]
2.1.801 [C:\Program Files\dotnet\sdk]
2.1.802 [C:\Program Files\dotnet\sdk]
2.2.205 [C:\Program Files\dotnet\sdk]
2.2.301 [C:\Program Files\dotnet\sdk]
3.0.100 [C:\Program Files\dotnet\sdk]
3.1.102 [C:\Program Files\dotnet\sdk]
3.1.300 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.18 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.18 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.18 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

  • The IDE: VS 2019 16.6.0
@water1st water1st changed the title binding wrong value in for loop Blazor binding wrong value in for loop May 28, 2020
@javiercn
Copy link
Member

@water1st thanks for contacting us.

This is a known limitation on the Razor compiler. When using the i variable inside the for loop, the code in the event handler closes over the loop variable which is what is causing the issue.

There are a couple of things you can do to avoid this:

  • Use a foreach loop instead of a for loop as that will give you the correct semantics
  • Declare a temporary variable within the loop body and assign it to the value of the loop variable at the time and use the temporary variable through the code instead.

@javiercn javiercn added the area-blazor Includes: Blazor, Razor Components label May 28, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Jun 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

No branches or pull requests

2 participants