【问题标题】:Reset input field value if value is invalid in Blazor如果 Blazor 中的值无效,则重置输入字段值
【发布时间】:2023-03-24 09:14:01
【问题描述】:

我在 for 循环中绑定了一些文本字段。

<Input type="text" @onchange='(ChangeEventArgs e)=>DataChange(e,item)' value="@item.value" />

如果用户在输入字段中输入任何内容,我将在 DataChange 函数中进行自定义验证。

private void DataChange(ChangeEventArgs e, PnL pnl)
  {
    if(e.Value.ToString().Contains(10))
     {
       pnl.value = e.Value.ToString();
     }
  }

如果更改有效,则只有我为列表中的项目分配值。 但如果它无效,我需要将值重置为原始值。

我曾尝试致电StateHasChange(),但这并没有帮助。 有人可以帮忙吗?

【问题讨论】:

  • 您真的要在用户输入时重置文本框吗?他们可能不喜欢那样。
  • 一旦元素失去焦点,函数就会触发。使用 onchanges 事件可以正常工作。

标签: c# blazor blazor-server-side asp.net-blazor


【解决方案1】:

试试这个:

private async Task DataChange(ChangeEventArgs e, PnL pnl)
  {
    if(e.Value.ToString().Contains(10))
     {
       pnl.value = e.Value.ToString();
     }
else
  {
    var tempValue = pnl.value;
    pnl.value = string.Empty();
    await Task.Yield();
    pnl.value = tempValue;
  }
 }

所以这里发生的事情是这样的。

  1. 代码与await Task.Yield同步运行。
  2. 此时pnl.value是一个空字符串。
  3. DataChange 让 Blazor 事件处理程序执行,该事件处理程序将渲染操作加载到渲染器队列。
  4. Yield 允许渲染器为其渲染队列提供服务,并重新渲染组件。 pnl.value 为空白 - 与上次渲染不同 - 因此输入在 DOM 中得到更新。
  5. yield 之后的代码现在运行完成,将 pnl.value 设置回原来的值。
  6. DataChange 完成,Blazor 事件处理程序将第二个渲染操作加载到渲染器队列中,现在随着值再次发生变化,它会重新渲染输入。

在您的代码中,所有内容都是同步运行的。您可以多次调用StateHasChanged,渲染器只有在DataChange 完成后才获得任务时间来运行它的队列。此时渲染器仍然认为输入设置为pnl.value 的原始值(不是编辑后的值),因此 DOM 没有得到更新。

CodeProject 上有一篇更详细的文章 - https://www.codeproject.com/Articles/5310624/Blazor-UI-Events-and-Rendering

【讨论】:

  • 所以这里 Task.Yield() 伪造了一个异步进程,对吧?
  • 是和不是。使用 Yield(或 Task.Wait)它是异步的。在 Blazor 事件中,一切都发生在同步上下文线程上。调用 StateHasChanged 会在渲染器队列上排队 RenderFragment,但仅此而已。如果 SC 线程被事件代码阻塞,则渲染器无法为其队列提供服务。你 Yield 或 Task.Delay() 让它发生。
【解决方案2】:

@onchange发生时,绑定已经结束,所以此时无效的字符串在pnl.value中。

其中一个解决方案可能是用于绑定的额外属性。 value 属性只有在tempVal 有效时才会改变,否则会重置tempVal

<input type="text" @bind-value="item.tempVal" />

@code {
    PnL item = new() { value = "hello10hi", tempVal = "hello10hi" };//valid values
    class PnL
    {
        public string value { get; set; }
        string _tempVal;
        public string tempVal { get => _tempVal; set { _tempVal = value; DataChange(value, this); } }

        void DataChange(string newVal, PnL pnl)
        {
            if (newVal.Contains("10"))//is valid
            {
                pnl.value = newVal;
            }
            else
            {
                pnl.tempVal = pnl.value;
            }
        }
    }

}

编辑 (代码已更新)。

问题是,tempVal在写入时没有更新,所以它仍然是默认值,所以分配value后没有变化,因此UI中没有更新。

bind-value 将始终更新 tempVal。那里的“问题”是我们丢失了onechange 代码(因为我们使用了bind)。因此,我必须与 tempVal 属性内的更改进行交互。

【讨论】:

  • 由于某种原因,当您使用有效值取消焦点然后插入无效值时,它会起作用...给我一点时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2014-10-19
相关资源
最近更新 更多