Hadi Ranjbar
Hadi Ranjbar

Reputation: 19

having issue with Rerendring component blazor

I'm having problem using HstateHasChanged in Blazor, I want to rerender the Categories component every time when I add a new category. This is the code that I was expecting to work:

MyCategories.razor

@page "/categories"
    @inject IModalService Modal
    @inject ICategoryService CategoryService
    @implements IDisposable
    
    <div class="col-md-8 col-sm-12 col-xs-12 ">
        <button @onclick="@(()=>Modal.Show<AddCategory>("New Category"))" class="btn btn-primary">Add New</button>
    
        @if (CategoryService.Categories == null)
        {
            <p><em>Loading...</em></p>
        }
        else
        {
            <table class="table">
                <thead>
                    <tr>
                        <th>Title</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var category in CategoryService.Categories)
                    {
                        <tr>
                            <td>@category.Title</td>
                            <td><a href="#" class="btn btn-danger">Remove</a></td>
                        </tr>
                    }
                </tbody>
            </table>
        }
    </div>
    
    @code {
        protected override async Task OnInitializedAsync()
        {
            CategoryService.OnChange += StateHasChanged;
            await CategoryService.LoadCategoriesAsync();
        }
    
        public void Dispose()
        {
            CategoryService.OnChange -= StateHasChanged;
        }
    }

MyAddCategory.razor here I have created this component and call it in the categories. I have called this component in the categories.razor, and it will show a form in a modal.

@inject NavigationManager NavigationManager
    @inject IToastService ToastService
    @inject ICategoryService CategoryService
    @implements IDisposable
    
    <EditForm Model="category" OnValidSubmit="HandleSubmit">
        <DataAnnotationsValidator></DataAnnotationsValidator>
        <div class="form-group">
            <label for="title" class="required">Title</label>
            <InputText id="title" @bind-Value="category.Title" class="form-control"></InputText>
            <ValidationMessage For="@(()=>category.Title)" />
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </EditForm>
    
    @code {
        private Category category = new Category();
    
        public void Dispose()
        {
            CategoryService.OnChange -= StateHasChanged;
        }
    
        async void HandleSubmit()
        {
            var result= await CategoryService.AddCategoryAsync(category);
    
            if (result.Success)
            {
                CategoryService.OnChange += StateHasChanged;
                ToastService.ShowSuccess(result.Message);
                NavigationManager.NavigateTo("/categories");
            }
            else
            {
                ToastService.ShowError("An error has occured.");
            }
        }
    }

Upvotes: 2

Views: 143

Answers (1)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30410

Let's take a lok at your code:

        async void HandleSubmit()
        {
            var result= await CategoryService.AddCategoryAsync(category);
    
            if (result.Success)
            {
                CategoryService.OnChange += StateHasChanged;
                ToastService.ShowSuccess(result.Message);
                NavigationManager.NavigateTo("/categories");
            }

So you add a category with await CategoryService.AddCategoryAsync(category);. Does this raise CategoryService.OnChange? It should.

You register an event handler in the modal CategoryService.OnChange += StateHasChanged; and then immediately navigate away from ther page with NavigationManager.NavigateTo("/categories");

In MyCategories you get the CategoryService.Categories on initialization, but I see no where where you refresh the list.

        protected override async Task OnInitializedAsync()
        {
            CategoryService.OnChange += StateHasChanged;
            await CategoryService.LoadCategoriesAsync();
        }

You just call StateHasChanged (if CategoryService.OnChange is raised).

In the code you've shown us, the dots aren't joined up.

Adding a category should cause the category service to raise the OnChange event, and either any listeners should refresh CategoryService.Categories or it should refresh automatically on the add/delete/update.

Upvotes: 1

Related Questions