我要使用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
元素?
答案 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元素的内容,并且可以通过更改类名输出来更轻松地更改自动对焦目标。