Blazor 如何将焦点设置为InputText元素?
使用,我试图以编程方式将焦点设置为输入元素 不幸的是,这个示例使用了一个标准的Blazor 如何将焦点设置为InputText元素?,blazor,blazor-server-side,Blazor,Blazor Server Side,使用,我试图以编程方式将焦点设置为输入元素 不幸的是,这个示例使用了一个标准的,而我想将它用于一个 Microsoft示例使用的扩展方法采用ElementReference: 公共静态任务焦点(此ElementReference elementRef,IJSRuntime jsRuntime) { 返回jsRuntime.InvokeAsync( “exampleJsFunctions.focusElement”, elementRef); } 使用InputText,我看不出有办法获得这样的
,而我想将它用于一个
Microsoft示例使用的扩展方法采用ElementReference
:
公共静态任务焦点(此ElementReference elementRef,IJSRuntime jsRuntime)
{
返回jsRuntime.InvokeAsync(
“exampleJsFunctions.focusElement”,
elementRef);
}
使用InputText
,我看不出有办法获得这样的ElementReference
为我自己的Focus()
重载提供一个InputText
,但编译后没有显示可视化结果。所以我是无知的
我的问题
如何通过编程将焦点设置为
InputText
元素?您可以向InputText
添加id
参数,并修改focus
方法和JavaScript代码
public异步任务焦点(string elementId)
{
等待JSRuntime.InvokeVoidAsync(“exampleJsFunctions.focusElement”,elementId);
}
focusElement:函数(id){
常量元素=document.getElementById(id);
元素focus();
}
注意:这与其说是一个合适的解决方案,不如说是一个变通方法,但Blazor似乎并不直接支持它。有几种方法可以通过Blazor本机方式将焦点设置在元素上。这里有一个: 创建一个从
InputBase
派生的类,该类是InputText
的基类,具有与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;
}
}
}
公共类文本框:InputBase
{
私有元素引用InputRef;
受保护的覆盖void BuildRenderTree(RenderTreeBuilder)
{
builder.OpenElement(0,“输入”);
builder.AddMultipleAttributes(1,附加属性);
builder.AddAttribute(2,“类”,CssClass);
builder.AddAttribute(3,“值”,BindConverter.FormatValue(CurrentValue));
AddAttribute(4,“onchange”,EventCallback.Factory.CreateBinder
(这,_值=>CurrentValueAsString=_值,CurrentValueAsString));
builder.AddElementReferenceCapture(5,(值)=>{
InputRef=value;});
builder.CloseElement();
}
[Inject]IJSRuntime JSRuntime{get;set;}
AfterRenderAsync(bool firstRender)上受保护的重写异步任务
{
if(firstRender)
{
等待JSRuntime.InvokeVoidAsync(“exampleJsFunctions.focusElement”,InputRef);
}
}
受保护的重写bool TryParseValueFromString(字符串值、输出字符串结果、输出字符串验证错误消息)
{
结果=值;
validationErrorMessage=null;
返回true;
}
}
}
将此脚本放在_Host.cshtml文件的底部,就在下面
window.exampleJsFunctions=
{
焦点元素:函数(元素){
元素focus();
}
};
注意事项:
1.定义ElementReference变量以保存对输入元素的引用。
2.在BuildRenderTree方法中,我添加了捕获对
输入元素
3.从OnAfterRenderAsync方法调用focusElement JavaScript函数。
这只执行一次。请注意,我无法使用OnInitializedAsync
方法,但ElementReference变量可能
包含空值。
4.请注意,如果没有EditForm,则无法运行任何窗体组件
重要信息:当浏览器处于最小化状态时,按Ctrl+F5可能会干扰在文本元素中查看光标
使用代码:
提交
@代码{
私人雇员=新雇员();
私人无效手册提交()
{
Console.WriteLine(“OnValidSubmit”);
}
公营雇员
{
公共int ID{get;set;}=1;
公共字符串名称{get;set;}=“Nancy”;
}
}
我可以通过直接在Host.chtml文件中输入JavaScript来实现这一点(您也可以像演练建议的那样添加一个.js文件):
然后在razor页面(或组件)中,注入IJSRuntime
,添加ElementReference
,并将其绑定到要关注的元素(注意:方法名称已更改为符合命名标准):
@inject IJSRuntime
@使用JSInteropClass
将焦点设置为用户名
@代码{
私有元素引用用户名;
公共异步任务SetFocusAsync()
{
等待username.FocusAsync(JSRuntime);
}
}
在.NET5中,它将更加简单:
<button @onclick="() => textInput.FocusAsync()">Set focus</button>
<input @ref="textInput"/>
设置焦点
注意:此功能是在中引入的,因此在最终版本之前可能会更改
还值得一提的是,in是通过JS模块导出/导入引入的。所以,如果您仍然需要使用JSInterop,请不要污染窗口对象
更新:.NET 5已发布,此功能的工作方式不变
还发现了一个很酷的方法,它可以为您提供一些方便的JS技巧,例如:聚焦以前的活动元素,而不必使用@ref
。请参阅文档。现在.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 />
在任何事情上工作
@inject IJSRuntime JSRuntime
@using JsInteropClasses
<input @ref="username" />
<button @onclick="SetFocusAsync">Set focus on username</button>
@code {
private ElementReference username;
public async Task SetFocusAsync()
{
await username.FocusAsync(JSRuntime);
}
}
<button @onclick="() => textInput.FocusAsync()">Set focus</button>
<input @ref="textInput"/>
var JSHelpers = JSHelpers || {};
JSHelpers.setFocusByCSSClass = function () {
var elems = document.getElementsByClassName("autofocus");
if (elems.length == 0)
return;
elems[0].focus();
};
@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 />