为了账号安全,请及时绑定邮箱和手机立即绑定

如何制作使用 oninput 而不是 onchange 绑定的 EditForm 输入?

如何制作使用 oninput 而不是 onchange 绑定的 EditForm 输入?

C#
倚天杖 2023-07-22 15:39:24
假设我想使用 an EditForm,但我希望每次用户在控件中键入时触发值绑定,而不是仅在模糊时触发。举个例子,假设我想要一个InputNumber<int>能做到这一点的东西?我尝试过使用不同的方法,但bind-Value:event="oninput"没有成功。InputNumber通过复制 AspNetCore 源代码并覆盖/重写一些东西,我终于能够或多或少地获得我想要的东西。这是我的InputNumber<int>,它实现了我所希望的:    public class MyInputNumber: InputNumber<int>    {        protected override void BuildRenderTree(RenderTreeBuilder builder)        {            builder.OpenElement(0, "input");            builder.AddAttribute(1, "step", "any");            builder.AddMultipleAttributes(2, AdditionalAttributes);            builder.AddAttribute(3, "type", "number");            builder.AddAttribute(4, "class", CssClass);            builder.AddAttribute(5, "value", FormatValue(CurrentValueAsString));            builder.AddAttribute(6, "oninput", EventCallback.Factory.CreateBinder<string>(this, __value => CurrentValueAsString = __value, CurrentValueAsString));            builder.CloseElement();        }        // Copied from AspNetCore - src/Components/Components/src/BindConverter.cs        private static string FormatValue(string value, CultureInfo culture = null) => FormatStringValueCore(value, culture);        // Copied from AspNetCore - src/Components/Components/src/BindConverter.cs        private static string FormatStringValueCore(string value, CultureInfo culture)        {            return value;        }    }oninput请注意,序列 6 项中的“ ”是从基础方法onchange中的“”更改而来的。我想知道如何:InputNumberBuildRenderTree查看 的输出BuildRenderTree,以便我知道如何使用 Razor 和/或只是大致知道什么样的 Razor 语法相当于将来执行此操作。我从 AspNetCore 代码中的注释中了解到,这绝对不是执行此类操作的首选方法,而 Razor 是首选方法。EditContext我已经通过订阅的 来测试这在 .NET Core 3 Preview 7 ASP.NET Core Hosted Blazor 中是否有效,OnFieldChangedEvent并且可以看到,通过这种方法,我获得了我正在寻找的不同行为。希望有更好的方法。
查看完整描述

6 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

对于任何想知道的人,您可以子类化InputText以更改其呈现方式。例如,要使其使用该oninput事件,请创建包含以下内容的MyInputText.razor

@inherits Microsoft.AspNetCore.Components.Forms.InputText
<input @attributes="@AdditionalAttributes" class="@CssClass" @bind="@CurrentValueAsString" @bind:event="oninput" />

现在,当您使用<MyInputText @bind-Value="@someval" />它时,它的行为就像InputText除了它在每次击键时更新之外。


查看完整回答
反对 回复 2023-07-22
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

.NET Core 3.1 的官方文档input现在介绍了从组件继承并更改它以使其响应事件:

基于输入事件的InputText

使用InputText组件创建一个使用input事件而不是change事件的自定义组件。

使用以下标记创建一个组件,并按原样使用该组件InputText

剃刀:

@inherits InputText

<input
    @attributes="AdditionalAttributes" 
    class="@CssClass" 
    value="@CurrentValue" 
    @oninput="EventCallback.Factory.CreateBinder<string>(
        this, __value => CurrentValueAsString = __value, CurrentValueAsString)" />

该文档还给出了如何继承通用组件的示例:

@using System.Globalization
@typeparam TValue
@inherits InputBase<TValue>

因此,如果您将这两个组合在一起,您可以创建一个更改InputNumber组件行为的组件,如下所示:

@typeparam TNumber
@inherits InputNumber<TNumber>

<input 
   type="number"
   step="any"
   @attributes="AdditionalAttributes" 
   class="@CssClass" 
   value="@CurrentValue" 
   @oninput="EventCallback.Factory.CreateBinder<string>(
        this, __value => CurrentValueAsString = __value, CurrentValueAsString)" />

包含该type="number"部分将提供与现有部分相同的行为InputNumber(仅允许数字字符输入,使用向上和向下箭头递增/递减等)

如果将上面的代码放入 Blazor 项目的 Shared 文件夹中名为 InputNumberUpdateOnInput.razor 的文件中,则可以像使用普通 一样使用该组件,例如InputNumber

<InputNumberUpdateOnInput class="form-control text-right" @bind-Value="@invoiceLine.Qty" />

如果您想控制组件允许的小数位数,您需要将该step值作为传递给组件的参数。


查看完整回答
反对 回复 2023-07-22
?
HUWWW

TA贡献1874条经验 获得超12个赞

尝试这个:

 <input type="text" id="example1" @bind-value="@value" @bind-value:event="oninput" />

更多的...

不推荐您的方法。您应该使用 Razor 对组件进行子类化。

以下是应该有效的示例。它可以指导您如何获得解决方案。

包装的解决方案InputText

新输入文本.razor

<div class="form-group">
    <label class="col-form-label">@Label</label>
    <InputText Class="form-control" Value="@Value" ValueChanged="@ValueChanged" ValueExpression="@ValueExpression"></InputText>
</div>

@functions {
    [Parameter] string Label { get; set; }
    [Parameter] string Value { get; set; }
    [Parameter] EventCallback<string> ValueChanged { get; set; }
    [Parameter] Expression<Func<string>> ValueExpression { get; set; }
}

索引剃刀

<span>Name of the category: @category.Name</span>
<EditForm Model="@category">
    <NewInputText @bind-Value="@category.Name"/>
</EditForm>

InputBase您也可以像这样直接继承:

 @inherits InputBase<string>
 <input type="number" bind="@CurrentValue" id="@Id" class="@CssClass" />

希望这可以帮助...


查看完整回答
反对 回复 2023-07-22
?
holdtom

TA贡献1805条经验 获得超10个赞

我发现如果他/她避免使用@bind而是手动绑定,就可以做到这一点,如下所示:


<InputText Value=@MyValue @oninput=@HandleInputChange ValueExpression=@(() => MyValue) />


@{

  // This will change for every character which is entered/removed from the input

  Public string MyValue { get; set; }


  void HandleInputChange(ChangeEventArgs args)

  {

    MyValue = args.Value.ToString();

  }


}

我仍然不太明白为什么这有效。我认为这是因为参数AdditionalAttributes。它将oninput属性传递给更新您的值的 html<input>元素,因此您不再依赖回调ValueChanged来更新您的值。


查看完整回答
反对 回复 2023-07-22
?
一只名叫tom的猫

TA贡献1906条经验 获得超2个赞

好吧,在浏览源代码(特别是查看属性 CurrentValueAsString 和 CurrentValue)后,我已经弄清楚了这一点。这是我提出的用于制作文本输入的解决方案,该文本输入可以在输入上正确触发字段更改事件:


    public class InputTextCode : InputBase<string>

    {

        protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)

        {

            result = value;

            validationErrorMessage = null;

            return true;

        }

    }

@inherits InputTextCode;


<input type="text" id="@Id" class="@Class" @bind-value="CurrentValueAsString" @bind-value:event="oninput" />

如果这可以是开箱即用的输入组件上的一个易于配置的选项,那就太好了,但至少有一种方法可以做到这一点,不会让我起鸡皮疙瘩。


查看完整回答
反对 回复 2023-07-22
?
开满天机

TA贡献1786条经验 获得超12个赞

InputNumber如果你想保留默认事件,我通常会这样解决onchange:


<p>

    <InputNumber @bind-Value="myValue" @oninput="@(e => Int32.TryParse(e.Value.ToString(), out myValue))" />

</p>

<p>

    myValue: @myValue

</p>


@code {

    private int myValue = 0;

}

可空整数:


<p>

    <InputNumber @bind-Value="myValue" @oninput="@(e => myValue = int.TryParse(e.Value.ToString(), out int tmp) ? (int?)tmp : null)" />

</p>

<p>

    myValue: @myValue

</p>


@code {

    private int? myValue = 0;

}

如果你想保留InputText默认onchange事件但仍然做出反应,oninput我通常会这样做:@oninput="@(e => <bind-value variable> = e.Value.ToString())"


例如:


<InputText @bind-value="@Model.Username" @oninput="@(e => Model.Username = e.Value.ToString())" />

如果您希望使用oninput事件而不是事件,那么这里是来自https://learn.microsoft.com/onchange的 .NET 7的完整示例:


示例模型.cs:


using System.ComponentModel.DataAnnotations;


public class ExampleModel

{

    [Required]

    [StringLength(10, ErrorMessage = "Name is too long.")]

    public string? Name { get; set; }

}

共享/自定义输入文本.razor:


@inherits InputText


<input @attributes="AdditionalAttributes" 

       class="@CssClass" 

       @bind="CurrentValueAsString" 

       @bind:event="oninput" />

页面/FormExample7.razor:


@page "/form-example-7"

@using Microsoft.Extensions.Logging

@inject ILogger<FormExample7> Logger


<EditForm Model="@exampleModel" OnValidSubmit="@HandleValidSubmit">

    <DataAnnotationsValidator />

    <ValidationSummary />


    <CustomInputText @bind-Value="exampleModel.Name" />


    <button type="submit">Submit</button>

</EditForm>


<p>

    CurrentValue: @exampleModel.Name

</p>


@code {

    private ExampleModel exampleModel = new();


    private void HandleValidSubmit()

    {

        Logger.LogInformation("HandleValidSubmit called");


        // Process the valid form

    }

}

查看完整回答
反对 回复 2023-07-22
  • 6 回答
  • 0 关注
  • 128 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信