Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the Blazor UI component doesn't update after delete event?

Why the Blazor UI doesn't update after delete event:

My Component:

<table class="table table-striped">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Example</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var trainingTechnique in TrainingTechniques) {
        <tr>
            <td>@trainingTechnique.Id</td>
            <td>@trainingTechnique.Name</td>
            <td>@trainingTechnique.Example</td>
            <td>
                <button type="button" 
                        class="btn btn-danger" 
                        @onclick="@(async () => await DeleteTechnique(trainingTechnique.Id))">
                    Delete
                </button>

            </td>
        </tr>
        }
    </tbody>
</table>

My Component code behind:

public class TrainingTechniqueViewPageBase : ComponentBase
    {
        public List<TrainingTechniqueView> TrainingTechniques { get; set; }
        [Inject] 
        public ITrainingTechniqueConsumer TrainingTechniqueConsumer { get; set; }

        protected TrainingTechniqueForm TrainingTechniqueForm { get; set; } 
        protected override async Task OnInitializedAsync()
        {
            TrainingTechniques = (await TrainingTechniqueConsumer.GetTechniques()).ToList();
        }

        public async void TrainingTechniqueForm_OnSave()
        {
            TrainingTechniques = (await TrainingTechniqueConsumer.GetTechniques()).ToList();
            StateHasChanged();
        }

        protected void AddTrainingTechnique()
        {
            TrainingTechniqueForm.Show();
        }

        protected async Task DeleteTechnique(int id)
        {
           await (TrainingTechniqueConsumer.DeleteTrainingTechnique(id));
            this.StateHasChanged();

        }
    }
}

The Delete Method:

public async Task DeleteTrainingTechnique(int id)
{
    await _httpClient.DeleteAsync($"training/trainingtechniques/{id}");
}
like image 973
Anyname Donotcare Avatar asked Apr 08 '20 00:04

Anyname Donotcare


People also ask

What is OnInitializedAsync in Blazor?

Component initialization ( OnInitialized{Async} ) Blazor apps that prerender their content on the server call OnInitializedAsync twice: Once when the component is initially rendered statically as part of the page. A second time when the browser renders the component.

How do you dispose of Blazor components?

If a component implements IDisposable, the Dispose method will be called when the component is removed from the UI. You can use Dispose method to release unmanaged resources, unhook events, dispose DotNetObjectReference instances to avoid memory leak. Refer to the following code sample.

What is StateHasChanged Blazor?

Platform: Blazor Category: General. The StateHasChanged is a method in ComponentBase that notifies state changes to a component.


3 Answers

Solution 1: Reload the TrainingTechniques list from the source

private async Task Delete(int id)
{
    await TrainingTechniqueConsumer.DeleteTrainingTechnique(id);
    TrainingTechniques = (await TrainingTechniqueConsumer.GetTechniques()).ToList();
}

Solution 2: Remove the item form the list:

<table class="table table-striped">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Example</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var trainingTechnique in TrainingTechniques)
        {
            <tr>
                <td>@trainingTechnique.Id</td>
                <td>@trainingTechnique.Name</td>
                <td>@trainingTechnique.Example</td>
                <td>
                    <button type="button" class="btn btn-danger" @onclick="@(() => DeleteTechnique(trainingTechnique.Id))">Delete</button>
                </td>
            </tr>
        }
    </tbody>
</table>

And the Delete method:

private async Task Delete(int id)
{
    TrainingTechniques.RemoveAll(x => x.Id == Id);
    await TrainingTechniqueConsumer.DeleteTrainingTechnique(id);
}
like image 160
tbdrz Avatar answered Nov 08 '22 16:11

tbdrz


Remove the item from the list that has the binding to the UI.

protected async Task DeleteTechnique(int id)
{
    await (TrainingTechniqueConsumer.DeleteTrainingTechnique(id));
    TrainingTechniques.Remove(TrainingTechniques.Single(x => x.Id == id));
}

I think it is better to pass the item it self instead of an Id. For example the delete could be:

protected async Task DeleteTechnique(TrainingTechniqueView corpse)
{
    await (TrainingTechniqueConsumer.DeleteTrainingTechnique(corpse.Id));
    TrainingTechniques.Remove(corpse);
}
like image 33
Zsolt Bendes Avatar answered Nov 08 '22 17:11

Zsolt Bendes


I had the same problem and almost same UI as yours but my problem was instead of defining TrainingTechniques as List, I'd defined it as IEnumerable. So instead of:

public IEnumerable<TrainingTechniqueView> TrainingTechniques { get; set; }

I changed it as:

public List<TrainingTechniqueView> TrainingTechniques { get; set; }

And then using one of solutions suggested by @Inktkiller.

like image 31
VahidShir Avatar answered Nov 08 '22 18:11

VahidShir