Home > Software engineering >  blazor bindValue vs EventCallback<T> ValueChanged
blazor bindValue vs EventCallback<T> ValueChanged

Time:10-07

so i want to do something with logic for dicts that can be chosed from select list

basic example is

   <MudSelect T="int" @bind-Value="@model.dict1" For="@(() => @model.dict1)" >                
                    <MudSelectItem T="int"  Value="1">1</MudSelectItem>
                    <MudSelectItem T="int" Value="2">2</MudSelectItem>
    </MudSelect>

now i want to wrap it in to own component lets say DictListComponent.razor and to be used like

 <DictMudSelectComponent T="int" @bind-Value="@model.dict1" For="@(() => @model.dict1)" TableName="test" ></DictMudSelectComponent>

so i have

<MudSelect T="T" @bind-Value="@Value" For="@For">//todo some logic here to generate list dynamicly
<MudSelectItem T="int" Value="1">1</MudSelectItem>
<MudSelectItem T="int" Value="2">2</MudSelectItem>
</MudSelect>

@code {
[Parameter]
public Expression<Func<T>> For { get; set; }

private T? _value;

[Parameter]
public T? Value
{
    get => _value;
    set 
    { 
        _value = value;
        if (ValueChanged.HasDelegate)
            ValueChanged.InvokeAsync(_value);
    }
}

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

[Parameter]
public string TableName { get; set; } = "";

what am i missing here for this to work ? it freazes app when im on page that shold render this form. in debug i see that ValueChanged.InvokeAsync(_value) is executing always again and again even / cpu100% etc.

thanks and regards

CodePudding user response:

The problem is that your MudSelect is triggering the Setter on a Parameter, which then Invokes the callback, which then invokes the Setter on the Parameter again.

You could try:

[Parameter]
public T? Value
{
    get => _value;
    set 
    { 
        if (value != _value)
        {
            _value = value;
            if (ValueChanged.HasDelegate)
                ValueChanged.InvokeAsync(_value);
        }
    }
}

Or, preferably, do not change a parameter value from within the component itself:

<MudSelect T="T" 
           Value=@_value 
           ValueChanged=@((async (v) => await ValueChanged.InvokeAsync(v))
           For="@For">
    //todo some logic here to generate list dynamicly
    <MudSelectItem T="int" Value="1">1</MudSelectItem>
    <MudSelectItem T="int" Value="2">2</MudSelectItem>
</MudSelect>

@code {
    [Parameter] public T? Value { get; set; } 
    [Parameter] public EventCallback<T> ValueChanged { get; set; }

    private T? _value;

    protected override void OnParametersSet()
    {
        _value = Value;
    }
}

You can then bind to the Value property of DictMudSelectComponent in the containing component as normal.

  • Related