Blazor(客户端)StateHasChanged()不更新页面
Blazor (Client-side) StateHasChanged() not updating page
我的页面(组件)上有一个按钮,单击它会调用 Refresh() 方法。此方法然后调用 StateHasChanged(),但不会重新加载页面。 GetData() 正在调用外部 API 从数据库加载数据。
<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();
}
我的页面(组件)也有一个表单,其中包含可以更改的预加载输入。我希望用户能够编辑表单,但能够通过单击按钮刷新页面以取回原始数据。这适用于以前版本的 Blazor,是否存在已知问题?
@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>
您需要将您的值设置回原来的值。 StateHasChanged
不刷新页面。它重置组件以检查 RenderTree 以查看是否应更新 dom 元素 - 但由于您的值未更改,因此不会更新您正在寻找的方式。
调用 GetData()
而不是 StateHasChanged
应该适用于您的情况,但您可能希望存储值而不是再次点击 API。
我简化了您的代码以提供一个工作示例:
@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 = "testfrom@test.com",
MAILTO = "testto@test.com",
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; }
}
}
我是通过绑定一个字符串值来实现的。您不必在正文页面上显示该值即可工作。我将字符串从大写更改为小写。有趣的是这只适用于字符串值。
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; }
}
正如所有其他答案所解释的那样,有多种方法可以正确重置您的表单,但是 none 除了 BrinkDaDrink 答案告诉您如何通过按下按钮刷新页面。
我认为 BrinkDaDrink 的回答增加了不必要的复杂性。
我的解决方案是创建一个名为 refresh 的空组件页面,如下所示:
@page "/refresh"
@inject NavigationManager NavigationManager
@code {
protected override void OnInitialized()
{
NavigationManager.NavigateTo("");
}
}
此页面将立即重定向到您的原始页面并立即刷新页面和所有数据。
您可以在您的原始页面中创建一个刷新方法,如下所示:
public void RefreshPage()
{
NavigationManager.NavigateTo("refresh");
}
这比目前提供的任何其他解决方案更快地解决了您提到的问题:
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
您还可以通过将以下内容添加到刷新页面来使用它向刷新页面传递参数:
@page "/refresh"
@page "/refresh/{text}"
@inject NavigationManager NavigationManager
@code {
[Parameter]
public string Text { get; set; }
protected override void OnInitialized()
{
NavigationManager.NavigateTo(Text);
}
}
我的页面(组件)上有一个按钮,单击它会调用 Refresh() 方法。此方法然后调用 StateHasChanged(),但不会重新加载页面。 GetData() 正在调用外部 API 从数据库加载数据。
<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();
}
我的页面(组件)也有一个表单,其中包含可以更改的预加载输入。我希望用户能够编辑表单,但能够通过单击按钮刷新页面以取回原始数据。这适用于以前版本的 Blazor,是否存在已知问题?
@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>
您需要将您的值设置回原来的值。 StateHasChanged
不刷新页面。它重置组件以检查 RenderTree 以查看是否应更新 dom 元素 - 但由于您的值未更改,因此不会更新您正在寻找的方式。
调用 GetData()
而不是 StateHasChanged
应该适用于您的情况,但您可能希望存储值而不是再次点击 API。
我简化了您的代码以提供一个工作示例:
@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 = "testfrom@test.com",
MAILTO = "testto@test.com",
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; }
}
}
我是通过绑定一个字符串值来实现的。您不必在正文页面上显示该值即可工作。我将字符串从大写更改为小写。有趣的是这只适用于字符串值。
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; }
}
正如所有其他答案所解释的那样,有多种方法可以正确重置您的表单,但是 none 除了 BrinkDaDrink 答案告诉您如何通过按下按钮刷新页面。
我认为 BrinkDaDrink 的回答增加了不必要的复杂性。
我的解决方案是创建一个名为 refresh 的空组件页面,如下所示:
@page "/refresh"
@inject NavigationManager NavigationManager
@code {
protected override void OnInitialized()
{
NavigationManager.NavigateTo("");
}
}
此页面将立即重定向到您的原始页面并立即刷新页面和所有数据。
您可以在您的原始页面中创建一个刷新方法,如下所示:
public void RefreshPage()
{
NavigationManager.NavigateTo("refresh");
}
这比目前提供的任何其他解决方案更快地解决了您提到的问题:
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
您还可以通过将以下内容添加到刷新页面来使用它向刷新页面传递参数:
@page "/refresh"
@page "/refresh/{text}"
@inject NavigationManager NavigationManager
@code {
[Parameter]
public string Text { get; set; }
protected override void OnInitialized()
{
NavigationManager.NavigateTo(Text);
}
}