2
votes

I am fairly new to Blazor, so this issue may be more of a logic issue then an actual coding issue. Basically, my parent component is rendering a list based on a list of a child component. The problem is the list is not being updated.

For simplicity's sake, I created a small demo of the issue. Here is my main component:

@page "/"

<Counter @ref="MyCounter" />

<ul>
    @if (MyCounter?.TheList != null) 
    {
        @foreach (string s in MyCounter.TheList)
        {
            <li>@s</li>
        }
    }
</ul>

@code {
    Counter MyCounter;
}

Here is my counter component:

<div>
    <button @onclick="AddToList">Add to list</button>
</div>

@code {
    public List<string> TheList {get;set;} = new List<string>();
    private Random Rnd = new Random();

    private void AddToList()
    {
        int length = 5;
    
        var str_build = new System.Text.StringBuilder();        

        char letter;  
        for (int i = 0; i < length; i++)
        {
        double flt = Rnd.NextDouble();
        int shift = Convert.ToInt32(Math.Floor(25 * flt));
        letter = Convert.ToChar(shift + 65);
        str_build.Append(letter);  
        }

        TheList.Add(str_build.ToString());
        Console.WriteLine($"Added to the list: {str_build.ToString()}");
        Console.WriteLine($"The list now has {TheList.Count} items");        
    }
}

The behavior I expect to see happen is each time I click the button, I should see the newly added string pop up in the <ul> tag. However, what's actually happening is nothing is being rendered. The console log shows the new string plus the number of items in the list and that's all accurate. Blazor is just not re-rendering, probably because I have to somehow notify it that it needs to re-render. How can I get my expected behavior to work?

I created a fiddle of the problem here.

2

2 Answers

2
votes

I see you are storing the list of items in the child component. In case like this you have to tell the parent component to rerender your self because I have new data to display. You can do that by adding event callback to the child component and hook up to the event in the parent where you call the StateHasChanged() method. For code see modified fiddler

Other option could be to move the list to the parent component and pass the list as a parameter to the child component. In that case you would not need the event.

1
votes

@icemanind, I took a look at https://blazorfiddle.com/s/brcf1nvi. You can get this to work by setting up two way binding.

The key changes are:

  • change in parent index.razor
<Counter @ref="MyCounter" @bind-TheList="TheList" />
  • add to child counter.razor
public EventCallback<List<string>> TheListChanged {get;set;}

Please take a look at https://blazorfiddle.com/s/l5ucab8d.