I'm having trouble understanding blazor binding. I have created a basic sample to illustrate the problem I'm facing:
Suppose I want to create a component to choose a day and time like this: , with a Value property of type DateTime.
First, I create a component to hold the time input:
@* TimeInput.razor *@
<input type="time" @onchange=Changed [email protected]("HH:mm") required>
@code {
[Parameter] public DateTime Value { get; set; }
[Parameter] public EventCallback<DateTime> ValueChanged { get; set; }
public void Changed(ChangeEventArgs e)
{
Value = DateTime.Parse((string)e.Value!);
ValueChanged.InvokeAsync(Value);
}
}
Then I create a component with a select input and the TimeInput component created in the previous step:
@* DateTimeSelector.razor *@
<select @onchange=DateChanged>
@for (int i = 0; i < 7; i++)
{
var date = new DateTime(2022, 1, 1).AddDays(i);
<option [email protected]("yyyy-MM-dd")
selected=@(Value.Date == date)>
@date.ToString("dddd")
</option>
}
</select>
<TimeInput Value=Value ValueChanged=TimeChanged />
@code
{
[Parameter] public EventCallback<DateTime> ValueChanged { get; set; }
private void DateChanged(ChangeEventArgs arg)
=> Value = DateTime.Parse((string)arg.Value!).Add(Value.TimeOfDay);
private void TimeChanged(DateTime time)
=> Value = Value.Date.Add(time.TimeOfDay);
private DateTime value;
[Parameter]
public DateTime Value
{
get => value;
set
{
Console.WriteLine($"Value is {value}"); // FOR DEBUGGING
if (this.value != value)
{
this.value = value;
ValueChanged.InvokeAsync();
}
}
}
}
Finally, I test it in a page:
@page "/"
<p><DateTimeSelector @bind-Value=@dateTime /></p>
<p>Debug: <input type="text" value=@dateTime /></p>
@code {
private DateTime dateTime = new DateTime(2022, 1, 3, 17, 0, 0);
}
When the page is loaded, the component shows with value 2022-01-03 17:00 as expected:
But as soon as the user change a value (for example, from 5 pm to 6 pm), then the value resets to 0001-01-01 00:00:
If i take a look at the console I see this:
So why is this happening? Who's calling (twice) the setter for property Value with a default date? How can I fix it?
Well, just a small omission. In your DateTimeSelector
, you have to invoke with the value.
ValueChanged.InvokeAsync();
=> ValueChanged.InvokeAsync(value);