如何将焦点设置为InputText元素?

时间:2019-12-02 11:26:32

标签: blazor blazor-server-side

我要使用example from the Microsoft docs,以编程方式将焦点设置为输入元素。

不幸的是,该示例使用标准的<input type="text">,而我想将其用于InputText element

Microsoft示例使用扩展方法,该方法采用ElementReference

public static Task Focus(this ElementReference elementRef, IJSRuntime jsRuntime)
{
    return jsRuntime.InvokeAsync<object>(
        "exampleJsFunctions.focusElement", elementRef);
}

使用InputText,我看不到获得这样的ElementReference的方法。

改为使用Focus()为我自己的InputText提供重载,但已编译但未显示任何视觉结果。因此,我一无所知。

我的问题

如何通过编程将焦点设置为InputText元素?

5 个答案:

答案 0 :(得分:8)

.NET5 中,它将更加简单:

<button @onclick="() => textInput.FocusAsync()">Set focus</button>
<input @ref="textInput"/>

注意:此功能是.NET5 Preview 8中引入的,因此可能会有所变化,直到最终版本!

还值得一提的是,.NET5 RC1 JavaScript isolation是通过 JS模块导出/导入引入的。因此,如果您需要使用JS互操作,请不要污染window对象。

更新:.NET 5已发布,此功能保持不变。

还发现了一个不错的Nuget package,它可以为您提供一些便捷的JS技巧,例如:聚焦先前处于活动状态的元素而没有@ref 。请参阅文档here

答案 1 :(得分:2)

您可以将id参数添加到InputText并修改Focus方法和JavaScript代码。

public async Task Focus(string elementId)
{
    await JSRuntime.InvokeVoidAsync("exampleJsFunctions.focusElement", elementId);
}
focusElement: function (id) {
    const element = document.getElementById(id); 
    element.focus();
}

注意:这不是一个适当的解决方案,而是更多解决方法,但是Blazor似乎并不直接支持它。

答案 2 :(得分:1)

有几种方法可以将焦点放在Blazor本机方法上。这是一个:

创建一个派生自InputBase<string>的类,该类是InputText的基类,具有与InputText相同的功能。简而言之,将the code of InputText复制到您新创建的类中,并添加必要的功能。这是新的类:TextBox.cs

public class TextBox : InputBase<string>
    {

        private ElementReference InputRef;
        protected override void BuildRenderTree(RenderTreeBuilder builder)
    {

            builder.OpenElement(0, "input");
    builder.AddMultipleAttributes(1, AdditionalAttributes);
    builder.AddAttribute(2, "class", CssClass);
    builder.AddAttribute(3, "value", BindConverter.FormatValue(CurrentValue));
    builder.AddAttribute(4, "onchange", EventCallback.Factory.CreateBinder<string>
        (this, __value => CurrentValueAsString = __value, CurrentValueAsString));
    builder.AddElementReferenceCapture(5, (value) => {
                InputRef = value; } );


            builder.CloseElement();


    }
        [Inject] IJSRuntime JSRuntime { get; set; }

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                await JSRuntime.InvokeVoidAsync("exampleJsFunctions.focusElement", InputRef);
            }
        }

        protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)
        {
        result = value;
        validationErrorMessage = null;
        return true;
        }
        }

   } 

将此脚本放在_Host.cshtml文件的底部,正好位于

<script src="_framework/blazor.server.js"></script>

<script>

        window.exampleJsFunctions =
        {
            focusElement: function (element) {
               element.focus();
            }
        };
    </script>

注意事项: 1.定义一个ElementReference变量来保存对输入元素的引用。 2.在BuildRenderTree方法中,我添加了代码以捕获对    输入元素 3.从OnAfterRenderAsync方法中调用focusElement JavaScript函数。    这仅执行一次。请注意,我无法使用OnInitializedAsync    仅执行一次的方法,但是ElementReference变量可以    包含null。 4.请注意,如果没有EditForm ...,您将无法运行任何表单组件。

重要:在您的浏览器处于最小化状态时,按Ctrl + F5可能会干扰在文本元素中看到光标。

使用代码:

<EditForm  Model="@employee" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <TextBox @bind-Value="@employee.Name"/>

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

@code {
    private Employee employee = new Employee();

    private void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }

    public class Employee
    {
        public int ID { get; set; } = 1;
        public string Name { get; set; } = "Nancy";
    }
} 

答案 3 :(得分:1)

我可以通过直接在Host.chtml文件中输入JavaScript来完成此操作(您也可以按照演练提示添加.js文件):

Microsoft.Office.Interop.Word.Application oWord = (Microsoft.Office.Interop.Word.Application) w;
_activeDoc = oWord.ActiveDocument;
foreach(Microsoft.Office.Interop.Word.Shape s in _activeDoc.Shapes)
foreach(Microsoft.Office.Interop.Word.ContentControl cc in s.TextFrame.TextRange.ContentControls) {
    MessageBox.Show(cc.Title.ToString());
}

接下来,我在扩展文件中添加了扩展名(注意:由于命名标准,我将<script type="text/javascript"> window.exampleJsFunctions = { focusElement: function (element) { element.focus(); } } </script> 重命名为Focus

FocusAsync

然后在剃须刀页面(或组件)中,注入public static async Task FocusAsync(this ElementReference elementRef, IJSRuntime jsRuntime) { await jsRuntime.InvokeVoidAsync( "exampleJsFunctions.focusElement", elementRef); } ,添加IJSRuntime并将其绑定到要聚焦的元素上(注意:方法名称已更改为遵守命名标准):

ElementReference

答案 4 :(得分:1)

.net 5现在可能多余了,但是如果您不想对元素的ID进行硬编码或派生自己的输入类,一种简单的实现方法是在元素中添加CSS类,然后然后使用getElementsByClassName查找并设置焦点。

创建一个包含助手的脚本:

var JSHelpers = JSHelpers || {};

JSHelpers.setFocusByCSSClass = function () {
    var elems = document.getElementsByClassName("autofocus");
    if (elems.length == 0)
        return;
    elems[0].focus();
};

创建一个共享的'AutofocusByCSS'组件以处理在正确的时间调用JS:

@inject IJSRuntime JSRuntime
@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) JSRuntime.InvokeVoidAsync("JSHelpers.setFocusByCSSClass");
    }
}   

然后在您的页面中

<InputText @bind-Value="editmodel.someThing" class="form-control autofocus" />

<AutofocusByCSS />

可以处理任何归结为标准HTML元素的内容,并且可以通过更改类名输出来更轻松地更改自动对焦目标。