【问题标题】:How to create a InputText Component如何创建 InputText 组件
【发布时间】:2021-04-20 00:42:55
【问题描述】:

我正在尝试创建一个 Input 组件,它可以:

  • 按 Escape 时清除其值。

  • 在鼠标滚轮上更改其值。 我正在创建一个 Input 组件,因为我不想在所有 Inputs 元素中放入相同的代码,我需要从同一个站点管理所有元素。我有 6 天的 dis 问题。我正在阅读和搜索我可以使用但没有 100% 帮助我的信息。

     @inherits Microsoft.AspNetCore.Components.Forms.InputBase<string>
     @using Microsoft.AspNetCore.Components.Forms  
     @if (ReadOnly)
     {
       <InputText type="text"
                 tabindex="@TabIndex"
                class="@Class"
                id="@Id"
                style="@Style"
                maxlength="@MaxLength"
                min="@Min"
                max="@Max"
                placeholder="@Placeholder"
                readonly />
    }
    else
    {
       <InputText type="text"
                maxlength="@MaxLength"
                min="@Min"
                max="@Max"
                class="@Class"
                tabindex="@TabIndex"
                id="@Id"
                style="@Style"
                placeholder="@Placeholder" 
                @attributes="@AdditionalAttributes"
                @bind-Value="@Value"
                @bind-Value:event="oninput"
                @onkeydown="@(e => { if (e.Code == "Escape") Value = Clear(); StateHasChanged(); })"
                @onmousewheel="CaptureScroll"
                />
    }
    
    
    
    @code{
    [Parameter]
    public string Type { get; set; }
    [Parameter]
    public string Class { get; set; }
    [Parameter]
    public string Placeholder { get; set; }
    [Parameter]
    public string Id { get; set; }
    [Parameter]
    public string Style { get; set; }
    [Parameter]
    public bool ReadOnly { get; set; }
    [Parameter]
    public int MaxLength { get; set; }
    [Parameter]
    public int Min { get; set; }
    [Parameter]
    public int Max { get; set; }
    [Parameter]
    public int TabIndex { get; set; }
    }
    

当我需要使用它时,我只需调用它:

&lt;HyperInput Type="text" Class="form-control" Id="inputName" TabIndex="1" @bind-Value="model.ModelName" /&gt;.

当我运行应用程序试图使其工作时,我遇到了这个错误:

错误:System.InvalidOperationException:Shared_Components.Forms.HyperInput 需要 EditContext 类型的级联参数。例如,您可以在 EditForm 中使用 Shared_Components.Forms.HyperInput。 在 Microsoft.AspNetCore.Components.Forms.InputBase1.SetParametersAsync(ParameterView parameters) at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext&amp; diffContext, Int32 frameIndex) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext&amp; diffContext, Int32 frameIndex) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext&amp; diffContext, Int32 newFrameIndex) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext&amp; diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange1 oldTree, ArrayRange`1 newTree) 在 Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder,RenderFragment renderFragment) 在 Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry) 在 Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()

我尝试使用 EditForm 包装 HyperInput 并且不起作用。

希望有人可以帮助我,我需要它。

编辑: 现在,我正在尝试使用 input 元素而不是 InputText 并且不继承 InputBase。我只加了:

private string _binder;
[Parameter]
public string Binder
{
    get => _binder;
    set => Set(value);
}
[ParameterAttribute] public EventCallback<string> BinderChanged { get; set; }
public async void Set(string value)
{
    _binder = value;
    await BinderChanged.InvokeAsync(value);
}

我对这个组件唯一能做的就是用退格键删除。 注意:我使用的是@bind-Binder,而不是使用@bind-Value

【问题讨论】:

  • InputText 设计用于带有模型的EditForm - 您出于某种原因需要 InputText 吗?你能用标准的input吗?
  • 是的,我可以使用标准的input

标签: razor blazor


【解决方案1】:

您可以使用经典的 DOM 事件,例如 onkeyuponmousewheel,让您的 HyperInput 工作对您有利。我强烈建议使用 InputText 固有的,因为它使您的组件更加强大。如果您开始使用,我在这里发布的版本。距离完成还差得很远。

其他组件的使用情况

为了展示EditContext 中的用法和双向绑定功能,我创建了一个简单的模型、一个显示元素和一个重置按钮

<EditForm Model="_model">
    <HyperInput @bind-Value="_model.Name" Options="@(new String[]{ "ABC", "DEF","TEST","SOMETHING"})" class="form-control" />
</EditForm>

<span>@_model.Name</span>\
<button @onclick="@(() => _model.Name = "My Testname")" >Reset</button>

@code
{
    public class TestModel
    {
        public String Name { get; set; } = "My test name";
    }

    private TestModel _model = new TestModel();

}

超级输入

@inherits InputText

<input type="text" @bind-value="Value" @onkeyup="ClearInput" @onmousewheel="OnMouseWheelUp" @attributes=AdditionalAttributes />

@code {

    [Parameter]
    public IReadOnlyList<String> Options { get; set; }

    private Int32 _index = 0;

    public void ClearInput(KeyboardEventArgs args)
    {
        if(args.Key == "Escape")
        {
            //CurrentValue triggers the update process
            base.CurrentValue = String.Empty;
        }
    }

    public void OnMouseWheelUp(WheelEventArgs args)
    {
        Int32 nextIndex;
        if(args.DeltaY > 0)
        {
            nextIndex = _index + 1;
        }
        else
        {
            nextIndex = _index - 1;

        }

        SuggestInput(nextIndex);
    }

    private void SuggestInput(Int32 requestedIndex)
    {
        if(Options == null || Options.Count == 0) { return;  }

        if(requestedIndex < 0 && Options.Count > 0)
        {
            _index = 0;
            CurrentValue = Options[0];
        }
        else if(requestedIndex < Options.Count)
        {
            _index = requestedIndex;
            CurrentValue = Options[requestedIndex];
        }
    }
}

如果按下退出按钮,CurrentValue 将设置为空字符串并且文本框为空。 CurrentValue 将触发更新过程。对于鼠标滚轮,有一个由参数Options 表示的选项列表和一个负责记住列表中当前位置的本地字段。

WheelEventArgs 有一个属性DeltaY。如果向上滚动,则此值为负数。如果向下滚动,则值为正数。

我做了一个简单的“限制器”逻辑。如果您到达列表的边界(向上或向下),则不会再发生任何事情。但当然,您可以将其更改为循环缓冲区或其他任何您想到的东西。

【讨论】:

  • 当我使用组件并将值与您的代码绑定时,当我尝试从组件中获取值时无法获取新值。例如,如果我使用您的组件并绑定它,并且在我编辑值之后我不会得到编辑的值 if 就像输入绑定一样。
  • 必须有await ValueChanged.InvokeAsync(Value)OnFocusOut和当ClearInput方法结束时绑定值在编辑后更新。
  • 这就是为什么 InputBase 固有的好处。这部分由 InputBase 处理。不过你说得对,示例中我没有考虑过这种情况。
  • 嗨@MAERT。你有时间检查我的更新吗?它对你有用吗?
  • 哦,不抱歉。我还没有尝到你的更新。我的代码按预期运行。
猜你喜欢
  • 2012-08-10
  • 1970-01-01
  • 2010-11-11
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 2012-05-29
  • 2021-03-26
相关资源
最近更新 更多