-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
I opened this issue in the AspNetCore.Docs repository, and was told to open an issue here after some discussion.
I'm wondering if there's a functional difference between using @bind-{PARAMETER}:set and {PARAMETER}Changed when dealing with component parameters. From my testing, they appear to behave the same.
From the original issue:
I'm not sure what you mean by 'functional difference.'
The earlier docs mention that @bind:get/@bind:set differs from something like @onchange in that it informs the framework that your intent is to modify the value. So it'll update the DOM after the handler. When dealing with component parameters, though, you're not really dealing with the DOM anymore, right?
If you'll excuse the slightly longer example:
MyPage.razor:
@page "/"
<div>@_value</div>
<input value="@_value" @onchange="HandleValueChanged" />
<input @bind:get="_value" @bind:set="HandleBoundValueChanged" />
@code
{
private string _value = string.Empty;
private void HandleValueChanged(ChangeEventArgs args) =>
HandleBoundValueChanged(args.Value?.ToString() ?? string.Empty);
private void HandleBoundValueChanged(string value) =>
_value = value.Length > 3 ? value[..3] : value;
}With the above code, if I take the first input (old style change handling), and I type out "12345", it'll get turned into "123" and the <div> will show "123". If I then add "45" (so "12345" again), the <div> will continue showing "123", but the input will still have "12345".
The second input doesn't have this problem, because it uses @bind:get/@bind:set, and that's precisely the type of problem it solves.
I convert the "keep 3 characters in my input" logic into its own component which uses @bind:get/@bind:set:
ThreeCharacterInput.razor:
<input @bind:get="Value" @bind:set="HandleValueChangedAsync" />
@code
{
[Parameter]
public string Value { get; set; } = string.Empty;
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
private async Task HandleValueChangedAsync(string value) =>
await ValueChanged.InvokeAsync(value.Length > 3 ? value[..3] : value);
}Is there supposed to be any difference between these two uses below? From my testing, they both work the same (I can't reproduce the "12345" bug with either of them).
MyPage.razor:
@page "/"
<div>@_value</div>
<ThreeCharacterInput Value="@_value" ValueChanged="@(value => _value = value)" />
<ThreeCharacterInput @bind-Value:get="@_value" @bind-Value:set="@(value => _value = value)" />
@code
{
private string _value = string.Empty;
}So when I ask about "functional" differences, I mean is there an inherent reason to use one version over the other when dealing with component parameters? Is the guidance to use @bind-{PARAMETER}:get/@bind-{PARAMETER}:set with component parameters just to be consistent with HTML bindings? Am I missing some subtle issue in the non @bind-based approach?