Reputation: 505
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>
Upvotes: 12
Views: 25551
Reputation: 106
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);
}
}
Upvotes: 9
Reputation: 1
I did it by binding a string value. You don't have to display the value on the body page for it to work. I change the string from uppercase to lowercase. Funny thing is this only works with a string value.
NAVMENU ----------------------
<button type="button" class="btn btn-warning border-secondary" @onclick="runSearch">Search</button>
@code {
public string pageReload = "Search";
private void runSearch()
{
if (pageReload == "Search") { pageReload = "search"; } else { pageReload = "Search"; }
NavigationManager.NavigateTo($"/Page2/{pageReload}", false);
}
}
Page 2------------------------------------------------------------------------
@page "/Datatest2/{pageReload}"
<h1>page will now refresh every time</h1>
@code{
[Parameter]
public string pageReload { get; set; }
}
Upvotes: 0
Reputation: 33691
You need to set your values back to their original values. StateHasChanged
does not refresh the page. It resets the component to check the RenderTree to see if dom elements should be updated - but since your values have not changed it will not update the way you are looking for.
Calling GetData()
instead of StateHasChanged
should work in your case, but you may want to store the values instead of hitting the API again.
I simplified your code to provide a working example:
@page "/update-test"
<EditForm Model="@Item">
<div class="notifyParametersForm">
</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>
<button class="btn btn-warning" @onclick="ResetInputs">Refresh</button>
</EditForm>
@code {
EmailItem Item;
protected override async Task OnInitializedAsync()
{
try
{
GetData();
base.OnInitialized();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
protected void GetData()
{
Item = new EmailItem()
{
MAILFROM = "[email protected]",
MAILTO = "[email protected]",
EMAIL_SUBJECT = "subject",
};
}
public void ResetInputs()
{
GetData();
}
public class EmailItem
{
public string MAILTO { get; set; }
public string MAILFROM { get; set; }
public string EMAIL_SUBJECT { get; set; }
}
}
Upvotes: 0