Melon NG
Melon NG

Reputation: 2994

Why @ref in Blazor server-side does not render correctly after removed items?

Here is my code in front-end:

    @page "/"
    @inject IJSRuntime JSRuntime
    
    <ul>
        @foreach (TestClass i in TestList)
        {
            if (i.Count != 0)
            {
            <li>
                <button @onclick="() => RemoveVoid(i)" style="display:inline-block">Remove</button>
                <p @ref="@i.Reference" style="display:inline-block">@(string.Format("{0}×{1}", @i.Name, i.Count))</p>
                <button @onclick="() => AddVoid(i)" style="display:inline-block">Add</button>
            </li>
            }
        }
    </ul>
    
    @code{
        public class TestClass
        {
            public string Name;                
            public int Count=1;
            public ElementReference Reference;
    }
    List<TestClass> TestList = new List<TestClass>()
{
        new TestClass(){ Name="Apple" },
            new TestClass(){ Name="Pear" },
            new TestClass(){ Name="Banana" },
            new TestClass(){ Name="Orange" },
            new TestClass(){ Name="Melon" }
    };
    void AddVoid(TestClass i)
    {
        i.Count++;
        StateHasChanged();
        JSRuntime.InvokeVoidAsync("AppFunctions.Test", i.Reference);
    }
    void RemoveVoid(TestClass i)
    {
        i.Count--;
        StateHasChanged();
    }
}

And here is the code in JS:

window.AppFunctions = {   
    Test: function (o) {
        o.style.backgroundColor = "red";
        setTimeout(function () {
            o.style.backgroundColor = "white";
        }, 2000);
    }    
};

Now it looks like this:
enter image description here

Firstly, we remove the Pear to 0.

And then we add the Banana to 2.

enter image description here

Now you will find the highlight is on the Orange but not on the Banana correctly.

What's wrong with this?

Upvotes: 0

Views: 693

Answers (1)

enet
enet

Reputation: 45626

Use @key to control the preservation of elements and components When rendering a list of elements or components and the elements or components subsequently change, Blazor's diffing algorithm must decide which of the previous elements or components can be retained and how model objects should map to them. Normally, this process is automatic and can be ignored, but there are cases where you may want to control the process.

Your issue is solved by using the @key attribute like this:

<p @key="@i" @ref="@i.Reference" style="display:inline-block">@(string.Format("{0}×{1}", @i.Name, i.Count))</p>

Note: Calling the StateHasChanged method is not necessary...

Why don't you remove TestClass objects from the list with the Remove method ?

Upvotes: 1

Related Questions