I want to update a TodoItem
in a child component TodoComponent
passing a EventCallback
.
In my TodoPage.razor.cs
I've implemented an update method:
public async void UpdateTodo(TodoItem todoItem)
{
await Http.PutAsJsonAsync("todo", todoItem);
await RefreshTodos();
}
And then I'm trying to pass to the TodoComponent
that is responsible to render the object
@foreach (var item in @TodoItems)
{
<div class="row">
<CascadingValue Value=@item Name="TodoItem">
<TodoComponent UpdateCallback="@(async () => UpdateTodo(item))">
</TodoComponent>
</CascadingValue>
</div>
}
TodoComponent.razor
@inherits ListOfTodos.Client.Components.TodoComponentBase
<div class="input-group col-12">
<div class="input-group-prepend">
<div class="input-group-text">
<input type="checkbox" @bind="@TodoItem.IsDone" onclick="@UpdateCallback">
</div>
</div>
<div class="col-8">
<input type="text" class="form-control" @bind="@TodoItem.TaskName" oninput="@UpdateCallback" />
</div>
<div class="input-group-append">
<input type="date" @bind="@TodoItem.DueDate" />
</div>
</div>
Aditional info:
public async Task RefreshTodos()
{
TodoItems = await Http.GetFromJsonAsync<List<TodoItem>>("todo");
StateHasChanged();
}
public class TodoComponentBase : ComponentBase
{
[CascadingParameter(Name = "TodoItem")]
public TodoItem TodoItem { get; set; }
[Parameter]
public EventCallback<TodoItem> UpdateCallback { get; set; }
protected override Task OnInitializedAsync()
{
return base.OnInitializedAsync();
}
}
When I call the UpdateCallback
though onchange
or oninput
the TodoItem
comes like if it wasn't updated at all, I don't know if the binding is working as I intend it to do.
How do I properly pass the object to the child component and have it update correctly?
This is the github repo: https://github.com/DgoNeves/Blazor.ListOfTodos It works in memory so you don't need any database to run it.
Edit: I don't exactly know why this happens but apparently the controller call is behing for some reason.
I've figured it out!
@bind="@TodoItem.TaskName"
executes by default onChange
onInput
apparently happens before the onChange
so in the screenshot when I get 1 character behind it means that it did not update the TodoItem.TaskName
because that's the next step.
If I really want to call the API on every keystroke I need to change it to:
@bind-value="@TodoItem.TaskName" @bind-value:event="oninput" onchange="@UpdateCallback"
This way I change the binding to happen onInput
and I call the UpdateCallback
onChange
.
Because the onInput happens first
I get the updated value on onChange
therefore passing the correct value.
Source from where I've found this: https://github.com/dotnet/aspnetcore/issues/15554 He had exactly the same error as I did