Home > database >  Why when I delete item from list binds to component, it deletes the right item from the list but dup
Why when I delete item from list binds to component, it deletes the right item from the list but dup

Time:01-21

I have a strange behavior in Blazor server app.

When I have a list of object and I delete one of the items in the list, it deletes the right item in the list but it copies the data from the last item to the one before it.

It only happen when I bind the list data to my own component. If I bind it directly to an input element it wont happen.

I reproduce the behavior in a small code sample as follow, just try to delete the second item and see the behavior.

Thank for who may help ...

Blazor markup

 <table>
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (User user in _users)
        {
            <tr>
                <td><MyText @bind-Value="user.Id"></MyText></td>
                <td><MyText @bind-Value="user.Name"></MyText></td>
                <td @onclick="(() => DeleteUser(user))">delete</td>
            </tr>
        }
    </tbody>
</table>

Blazor Code

private List<User> _users = new List<User>();
private class User
{
    public string Id { get; set; } = "";
    public string Name { get; set; } = "";
}

protected override void OnInitialized()
{
    _users.Add(new User() { Id = "1", Name = "Adam" });
    _users.Add(new User() { Id = "2", Name = "Benny" });
    _users.Add(new User() { Id = "3", Name = "Charles" });
    _users.Add(new User() { Id = "4", Name = "David" });
    base.OnInitialized();
}

private void DeleteUser(User user)
{
    _users.Remove(user);
}

MyText Component

<input @bind-value="@Value" />

@code {

    public string _value = "";

    [Parameter]
    public EventCallback<string> ValueChanged { get; set; }

    [Parameter]
    public string Value
    {
        get
        {
            return _value;
        }
        set
        {
            if (_value != value)
            {
                _value = value;
                ValueChanged.InvokeAsync(value);
            }
        }
    }    
}

CodePudding user response:

You have to help the 'diffing engine' of Blazor a little. Use @key like this:


@foreach (User user in _users)
{
    <tr @key="user">
        <td><MyText @bind-Value="user.Id"></MyText></td>
        <td><MyText @bind-Value="user.Name"></MyText></td>
        <td @onclick="(() => DeleteUser(user))">delete</td>
    </tr>
}

  •  Tags:  
  • Related