【问题标题】:Blazor CascadingParameter won't update layout when I call it from a function, after an onclick event在 onclick 事件之后,当我从函数调用 Blazor CascadingParameter 时,它不会更新布局
【发布时间】:2021-12-01 02:16:32
【问题描述】:

我正在尝试使用布局中的 CascadingParameter 以通用方式管理我的网站的“加载”。
但是,在我调用“onclick”加载之后,我无法从“继承页面”EditForm 的“OnValidSubmit”函数中停止“加载”。

让我告诉你。
在我的 MainLayout 中,我设法显示加载 h2 或页面内容,无论它是什么:

<CascadingValue Value="this">
@if (load == true)
{
    <h2>Loading...</h2>
} else
{
    @Body
}
</CascadingValue>

@code 
{ 
   public bool load = false;

   //---------------------------
   // Setters
   public void Loading()
   {
      load = true;
   }

   public void StopLoading()
   {
      load = false;
   }
}

在从该 MainLayout 继承的其他页面中,我有一个 EditForm,它将检查用户名和密码是否与数据库匹配。
如果没有错误,它应该调用“加载”函数,然后在数据库中处理搜索,然后导航到主页。
所以我将“加载”功能添加到我的 EditForm 的“onclick”中,当我点击按钮时它会正确显示加载 h2:

    <EditForm Model="@user" OnValidSubmit="@TriggerLogin">
       <InputText id="name" placeholder="Email" @bind-Value="user.Username" inputmode="email" />
       <InputText id="password" placeholder="Mot de passe" @bind-Value="user.Password" type="password" inputmode="text" />
       <button class="button-pink" type="submit" @onclick="Layout.Loading">Se connecter</button>
   </EditForm>

然后使用我的“OnValidSubmit”函数对数据库进行研究:

private async Task TriggerLogin()
{
    if (members.Login(user) == true)
    {
        // Do stuff with accesstoken
        Layout.StopLoading();
        NavigationManager.NavigateTo("/commandes");
    }
    else
    {
        Layout.StopLoading();
        error = "Wrong password or username";
    }
}

但是我的 StopLoading() 函数没有更新我的页面!
即使我的调试器说我在布局中正确输入了函数,布局也没有输入 html 部分的“else”,也没有显示“@Body”。
我尝试在布局中使用 this.StateHasChanged()(它唯一起作用的地方),但我正在寻找另一种解决方案,因为它不会显示错误消息。

如何强制仅布局刷新 html 部分? 谢谢

【问题讨论】:

  • error 变量是什么?你如何呈现它?
  • @HenriquePombo 是继承MainLayout的页面中的局部变量。所以private string error
  • 老实说,这是一种试图实现目标的非常混乱的方式。我把它归咎于微软的 ITab 示例。你不需要传递任何东西。将加载部分移动到表单组件本身并在那里管理进度。
  • 仅在OnValidSubmit 之后调用body 对我来说没有多大意义。您登录的地方是否有其他布局?在布局上显示正文后显示错误,它不会出现是有道理的。你有没有想过使用Toast
  • 您似乎在每个页面上手动执行授权检查。您应该简单地使用 [Authorize] 属性。对于任何其他类型的“通用”加载,您应该将加载相关逻辑放在需要耗时加载的组件中。

标签: c# blazor


【解决方案1】:

正常重载失败可以使用StateHasChanged();解决,所以试试

public void StopLoading()
{
   load = false;
   InvokeAsync(StateHasChanged);
}

--- 编辑---

如果这个 make 丢失了局部变量,则可以选择将这些变量移动到服务中。在我的示例中,我只为加载和错误执行此操作,但其余部分可以像加载一样完成。

public class LoadService {
    public bool Load {get;set;}
    public String ErrorMessage {get;set;}
}

然后更改您的代码:

@inject LoadService LoadService 
//... html part
@if (LoadService.Load== true)
{
    <h2>Loading...</h2>
}
//... html part
@code 
{ 
   //... html part
   public void StopLoading()
   {
      LoadService.Load = false;
      InvokeAsync(StateHasChanged);
    }
}

设置错误信息:

private async Task TriggerLogin()
{
   if (members.Login(user) == true)
   {
       // Do stuff with accesstoken
       Layout.StopLoading();
       NavigationManager.NavigateTo("/commandes");
    }
    else
    {
        Layout.StopLoading();
        LoadService.ErrorMessage = "Wrong password or username";
    }
}

别忘了在 Program.cs 中注册服务

builder.Services.AddSingleton<LoadService>();

【讨论】:

  • 是的,但我丢失了我正在填写继承 MainLayout 的页面的private string error。当我调用 StateHasChanged 时,布局从 else 传递,但它也丢失了我修改的这个局部变量。
  • 不需要将我的负载变量传递给服务。我正在使用 CascadingParameters 在“子”页面中修改布局中的负载变量。但实际上我可以使用您的逻辑来创建一个可以注入的 ErrorService。所以我可以在 Layout 中调用 StateHasChanged,同时可以访问存储在 ErrorService 中的错误,该错误是我在“子”页面中注入的。
  • 如果您愿意更改您的答案以指定我需要将错误存储在服务中,而不是加载值,我会接受您的回答!最好的问候
猜你喜欢
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多