What's is the recommended way to trigger a callback in the parent control using two way databinding when a property changed in the child control?
I have tried following but it's not triggering HandleValueChanged. Is there a conventional way to trigger OnValueChanged in the parent?
Parent Component
@page "/parent"
<h3>Parent Component</h3>
<ChildComponent @bind-Value="parentValue" @bind-Value:after="HandleValueChanged" />
<p>Parent Value: @parentValue</p>
@code {
private int parentValue = 0;
private void HandleValueChanged()
{
// Handle the value change event here
Console.WriteLine($"Value changed to: {parentValue}");
}
}
Child Component
<h3>Child Component</h3>
<input type="number" @bind="Value" />
@code {
[Parameter]
public int Value { get; set; }
[Parameter]
public EventCallback<int> ValueChanged { get; set; }
private async Task OnValueChanged(ChangeEventArgs e)
{
Value = int.Parse(e.Value.ToString());
await ValueChanged.InvokeAsync(Value);
}
}
OnValueChanged
inside the child component never gets executed, which means that the parent component never gets informed about the new property value at all, not just that HandleValueChanged
doesn't execute. You should also notice that <p>Parent Value: @parentValue</p>
doesn't update to a newer value when the child's input element is changed.
Is there a conventional way to trigger OnValueChanged in the parent?
The child component needs to execute OnValueChanged
(or, more correctly, the child component is the one that needs to execute ValueChanged.InvokeAsync()
).
I'm not exactly sure what you're trying to accomplish with the line Value = int.Parse(e.Value.ToString());
. It doesn't seem necessary when you're already binding Value
.
Here's the updated child component code:
<input type="number" @bind="Value" @bind:after="OnValueChanged" />
private async Task OnValueChanged()
{
await ValueChanged.InvokeAsync(Value);
}
Instead of doing :after
(and @bind
) in the child, you could use the value=
and onchange=
attributes, but it would be your responsibility to update Value
in the delegate. That's the point of :after
- it still lets you do 2-way data binding (you don't need to manually update the property yourself) but you can still trigger a method to run after the binding is updated.