Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor (Client-side) StateHasChanged() not updating page

I have a button on my page (component) that calls a Refresh() method when clicked. This method then calls the StateHasChanged(), but does not reload the page. The GetData() is calling an external API to load data from a database.

<button class="btn btn-warning" @onclick="Refresh">Refresh</button>

code {

protected override async Task OnInitializedAsync()
    {
        try
        {
            await GetData();
            base.OnInitialized();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

protected async Task GetData()
    {
        try
        {
            results = await HttpClient.GetJsonAsync<Results[]>(ServiceEndpoints.GET_RESULTS);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error retrieving data from Oracle.", ex.Message);
        }
    }

public void Refresh()
        {
            StateHasChanged();          
        }

My page (component) also has a form that has preloaded inputs that can be changed. I want the user to be able to edit the form, but be able to refresh the page by clicking the button to get back the original data. This was working on a previous version of Blazor, is there a known issue about this?

@page "/"
@inherits IndexBase

<EditForm Model="@results">
<label><strong>Select a job to view its current parameters</strong></label>
<div class="currentJobForm">

    <InputSelect id="jobSelect" @bind-Value="jobSelected">
        @foreach (var items in results)
        {
            <option value="@items.JOB_NAME">@items.JOB_NAME</option>
        }
    </InputSelect>
    <button class="btn btn-warning" @onclick="SaveChanges" disabled="@IsDisabled">Save</button>
    <button class="btn btn-warning" @onclick="Refresh">Refresh</button>
    <button class="btn btn-danger" @onclick="DeleteJob">Delete Job</button>
</div>    
    <label><strong>Notify Parameters</strong></label>
    <div class="notifyParametersForm">
        @foreach (var item in results.Where(i => i.JOB_NAME == jobSelected))
        {
            <div class="issueDescription">
                <label><strong>Issue Description</strong></label>
                <InputText id="issueDesc" @bind-Value="item.JOB_HEADER" placeholder="Enter New Issue Description" />
            </div>
            <div class="sendSlack">
                <label><strong>Send Slack</strong></label>
                <InputSelect id="sendSlackSelect" @bind-Value="item.SENDSLACK">
                    @foreach (var items in InitializeData.SendSlacks)
                    {
                        <option value="@items.SendSlackName">@items.SendSlackName</option>
                    }                        
                </InputSelect>
            </div>
            <div class="slackUser">
                <label><strong>Slack User</strong></label>
                <InputText id="slackUser" @bind-Value="item.SLACK_USER" placeholder="Enter New Slack User" />
            </div>
            <div class="slackChannel">
                <label><strong>Slack Channel</strong></label>
                <InputSelect id="sendSlackChannel" @bind-Value="item.SLACK_CHANNEL">
                    @foreach (var items in InitializeData.SlackChannels)
                    {
                        <option value="@items.SlackChannelName">@items.SlackChannelName</option>
                    }                        
                </InputSelect>
            </div>
            <div class="slackUrl">
                <label><strong>Slack URL</strong></label>
                <InputText id="slackUrlTextBox" @bind-Value="item.SLACK_URL" placeholder="Enter New Slack Url" />
            </div>
            <div class="sendMail">
                <label><strong>Send Mail</strong></label>
                <InputSelect id="sendMailSelect" @bind-Value="item.SENDMAIL">
                    @foreach (var items in InitializeData.SendMails)
                    {
                        <option value="@items.SendMailName">@items.SendMailName</option>
                    }
                </InputSelect>
            </div>
            <div class="mailFrom">
                <label><strong>From:</strong></label>
                <InputText id="from" @bind-Value="item.MAILFROM" placeholder="Enter New Mail From" />
            </div>
            <div class="mailTo">
                <label><strong>To:</strong></label>
                <InputText id="to" @bind-Value="item.MAILTO" placeholder="Enter New Mail To" />
            </div>
            <div class="subject">
                <label id="subjectLabel"><strong>Subject:</strong></label>
                <InputText id="subject" @bind-Value="item.EMAIL_SUBJECT" placeholder="Enter New Subject" />
            </div>
        }
    </div>
</div>
like image 884
bob82 Avatar asked Jan 03 '20 18:01

bob82


People also ask

How do I refresh Blazor page?

A page is reloaded/refreshed automatically at a specified interval using “NavigationManager” in OnAfterRender() method. Here the NavigateTo(“url”, forceLoad: true) method, is used to force load the browser based on the URI.

How do I refresh the Blazor component without reloading the page when database is updated?

How do I refresh the Blazor component without reloading the page when database is updated? You can refresh the Blazor component using the SignalR concept without reloading the page. When using SignalR, saving the changes in one page notifies the changes made to other clients.

Is Blazor server-side or client side?

The Blazor web framework allows Razor components to be hosted in different ways. They can run server-side in ASP.NET Core (Blazor Server) and client-side in the browser on a WebAssembly-based . NET runtime (Blazor WebAssembly or Blazor WASM).


1 Answers

As All the other answers explain there are various way to properly reset your form but none of them except BrinkDaDrink answer tell you how to refresh the page with a press of a button.

BrinkDaDrink answer add unnecessary complexity in my opinion.

My solution is to create an empty component page called refresh as follows:

@page "/refresh"
@inject NavigationManager NavigationManager

@code {

    protected override void OnInitialized()
    {
        NavigationManager.NavigateTo("");
    }

}

This page will immediately redirect to your original page refreshing the page and all of the data instantly.

You can create a refresh method in your original page as follows:

public void RefreshPage()
{
    NavigationManager.NavigateTo("refresh");
}

This solves the issue you mention much faster than any of the other solutions provided so far:

I want the user to be able to edit the form, but be able to refresh the page by clicking the button to get back the original data

You can also use this to pass parameters into your refresh page by adding the following to the refresh page:

@page "/refresh"
@page "/refresh/{text}"
@inject NavigationManager NavigationManager

@code {
    [Parameter]
    public string Text { get; set; }

    protected override void OnInitialized()
    {
        NavigationManager.NavigateTo(Text);
    }

}
like image 67
bortronx Avatar answered Sep 28 '22 19:09

bortronx