1
votes

I'm not clear on how to get a Blazor (Server) component to react to a change to one of it's parameters.

So, this is a cut-down version of my Component

@foreach (var msg in this.Data)
{
    <div class="bg-danger text-white">
        <div>@msg</div>
    </div>
}
@code
{
    [Parameter]
    public IList<Something> Data{ get; set; } = null!;
}

Then in my Page I have

<mycomponent Data="@StuffForComponent"><mycomponent>
@code
{
    private List<Something> StuffForComponent {get;} = new List<Something>();

    private async Task HandleSomeEvent()
    {
          var r = await this.Service.GetSomething().ConfigureAwait(false);
          this StuffForComponent.AddRange(r.Stuff);
    }
}

So the idea is that the Component gets created when the page loads, and the empty list gets passed to its input parameter.

Sometime later, we handle a user-event and this adds data to that list. However, the Component doesn't react to the changed list.

What do I need to do to make the component react to new entries being added, or deleted, from this list?

2
Should refresh. Did you try with StateHasChanged() after `AddRange? - dani herrera
By the way. You posted a question on BlazorConfirm about running on server side. LoL. BlazorConfirm is mine ;) but it is deprecated, some day I will update it to last version. Thanks about your interest. - dani herrera

2 Answers

0
votes

You need to add a callbackevent for the component to update properly. Try adding an eventcallback on the child component, then in your page use the "@Bind" to bind the page list to the child components internal list.

Here is the Child Component addition:

code{

...
 [Parameter]
    public EventCallback<List<Something>> DataChanged{ get; set; }
...
}

Here is the Page change

<mycomponent @bind-Data="StuffForComponent"><mycomponent>

This is called chained binding, and you can read more about this by searching for "chain" here

0
votes

I got this to work. It's a bit complex, but it may help others....

So I have a Razor Page with my component at the top of the page:

<mycomponent Data="@StuffForComponent"><mycomponent>

With that property defined:

private List<Something> StuffForComponent {get;} = new List<Something>();

I have a grid with a button per row. That button has an action defined:

[Parameter]
public IList<Action<object>>? Actions { get; set; }

When the button is clicked, it does whatever it has to do, and then it calls this action (which is a method defined on my page), passing information along.

That method inspects the data provided by button, and decides how it will update the List. As @dani mentioned, it requried StateHasChanged().

I implemented as:

private void MyCallbackMethod(object obj)
{
    this.StuffForComponent.Clear();
    if (obj is SomeType response)
    {
        InvokeAsync(() =>
        {
            this.StuffForComponent.Add(response.ValueToInspect
            ? new Something{ .... }
            : new Something{ .... });

            this.StateHasChanged();

        }).GetAwaiter().GetResult();
    }
}

It required InvokeAsync because this isn't the main UI thread.