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

假设我想使用 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

  1. 查看 的输出BuildRenderTree,以便我知道如何使用 Razor 和/或

  2. 只是大致知道什么样的 Razor 语法相当于将来执行此操作。

我从 AspNetCore 代码中的注释中了解到,这绝对不是执行此类操作的首选方法,而 Razor 是首选方法。EditContext我已经通过订阅的 来测试这在 .NET Core 3 Preview 7 ASP.NET Core Hosted Blazor 中是否有效,OnFieldChangedEvent并且可以看到,通过这种方法,我获得了我正在寻找的不同行为。希望有更好的方法。


倚天杖
浏览 131回答 6
6回答

慕码人8056858

对于任何想知道的人,您可以子类化InputText以更改其呈现方式。例如,要使其使用该oninput事件,请创建包含以下内容的MyInputText.razor:@inherits&nbsp;Microsoft.AspNetCore.Components.Forms.InputText <input&nbsp;@attributes="@AdditionalAttributes"&nbsp;class="@CssClass"&nbsp;@bind="@CurrentValueAsString"&nbsp;@bind:event="oninput"&nbsp;/>现在,当您使用<MyInputText @bind-Value="@someval" />它时,它的行为就像InputText除了它在每次击键时更新之外。

慕无忌1623718

.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值作为传递给组件的参数。

HUWWW

尝试这个:&nbsp;<input&nbsp;type="text"&nbsp;id="example1"&nbsp;@bind-value="@value"&nbsp;@bind-value:event="oninput"&nbsp;/>更多的...不推荐您的方法。您应该使用 Razor 对组件进行子类化。以下是应该有效的示例。它可以指导您如何获得解决方案。包装的解决方案InputText:新输入文本.razor<div&nbsp;class="form-group"> &nbsp;&nbsp;&nbsp;&nbsp;<label&nbsp;class="col-form-label">@Label</label> &nbsp;&nbsp;&nbsp;&nbsp;<InputText&nbsp;Class="form-control"&nbsp;Value="@Value"&nbsp;ValueChanged="@ValueChanged"&nbsp;ValueExpression="@ValueExpression"></InputText> </div> @functions&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;[Parameter]&nbsp;string&nbsp;Label&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[Parameter]&nbsp;string&nbsp;Value&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[Parameter]&nbsp;EventCallback<string>&nbsp;ValueChanged&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[Parameter]&nbsp;Expression<Func<string>>&nbsp;ValueExpression&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} }索引剃刀<span>Name&nbsp;of&nbsp;the&nbsp;category:&nbsp;@category.Name</span> <EditForm&nbsp;Model="@category"> &nbsp;&nbsp;&nbsp;&nbsp;<NewInputText&nbsp;@bind-Value="@category.Name"/> </EditForm>InputBase您也可以像这样直接继承:&nbsp;@inherits&nbsp;InputBase<string> &nbsp;<input&nbsp;type="number"&nbsp;bind="@CurrentValue"&nbsp;id="@Id"&nbsp;class="@CssClass"&nbsp;/>希望这可以帮助...

holdtom

我发现如果他/她避免使用@bind而是手动绑定,就可以做到这一点,如下所示:<InputText Value=@MyValue @oninput=@HandleInputChange ValueExpression=@(() => MyValue) />@{&nbsp; // This will change for every character which is entered/removed from the input&nbsp; Public string MyValue { get; set; }&nbsp; void HandleInputChange(ChangeEventArgs args)&nbsp; {&nbsp; &nbsp; MyValue = args.Value.ToString();&nbsp; }}我仍然不太明白为什么这有效。我认为这是因为参数AdditionalAttributes。它将oninput属性传递给更新您的值的 html<input>元素,因此您不再依赖回调ValueChanged来更新您的值。

一只名叫tom的猫

好吧,在浏览源代码(特别是查看属性 CurrentValueAsString 和 CurrentValue)后,我已经弄清楚了这一点。这是我提出的用于制作文本输入的解决方案,该文本输入可以在输入上正确触发字段更改事件:&nbsp; &nbsp; public class InputTextCode : InputBase<string>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; validationErrorMessage = null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }@inherits InputTextCode;<input type="text" id="@Id" class="@Class" @bind-value="CurrentValueAsString" @bind-value:event="oninput" />如果这可以是开箱即用的输入组件上的一个易于配置的选项,那就太好了,但至少有一种方法可以做到这一点,不会让我起鸡皮疙瘩。

开满天机

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    }}
打开App,查看更多内容
随时随地看视频慕课网APP