1

I am creating a Blazor PWA application using Visual Studio 2019. I use javascript to set focus to InputText fields during startup and certain key events.

    function focusInput(id){
    document.getElementById(id).focus();

    var tb = document.querySelector("#" + id);
    if (tb.select) {
        tb.select();
    }
}

and call it in my code behind like this

private string inputID = "user-id";
protected async override Task OnAfterRenderAsync(bool firstRender)
{
    await jsInterop.InvokeVoidAsync("focusInput", inputID);
}

This is the razor page

<EditForm Model="@login" class="card card-body mt-2">
    <div class="form-group row">
        <label for="userid" class="col-sm-2 col-form-label">User ID</label>
        <InputText id="@inputID" class="form-control" @bind-Value="@login.UserID" @onkeyup="(KeyboardEventArgs e) => KeyUpUserIDAsync(e)"/>
    </div>
    <div class="form-group row">
        <label for="message" class="col-sm-2 col-form-label">Message</label>
        <InputTextArea id="textarea-message" class="form-control" @bind-Value="@errorMessage" />
    </div>
</EditForm>

It works great except when I run it and load the first page which is the Login Page. Instead of getting focus in the field, the focus instead stays in the URL bar. If I refresh the page the InputeText gets focus. Note that all the other pages I navigate to after logging in do not have this problem. Just the initial page. I wrote to the console to make sure it was being called and it was. I also tried using autofocus attribute but it does not work either.

Mr Rob
  • 59
  • 7
  • 1
    Yeah, I've had this too. I suppose it is a browser issue. You probably ARE setting focus to the element, but then when the page finishes loading, the browser is setting focus back to the URL bar. Presumably, Chrome (or whatever) doesn't want you to hijack the user's intent if they are typing things into the URL bar. btw, .net 5 has a command for this: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.elementreferenceextensions.focusasync?view=aspnetcore-5.0 I'm not sure whether this will do anything different (I kind of doubt it), but you can try it. – Bennyboy1973 Sep 15 '21 at 01:19
  • Your doubts have been confirmed. I have another option that I found here https://www.meziantou.net/auto-focus-an-input-in-a-blazor-form.htm and will post back with an example if it works. – Mr Rob Sep 15 '21 at 01:54
  • I suspect that method will work about 95% of the time, and for the same reasons. – Bennyboy1973 Sep 15 '21 at 06:49

1 Answers1

0

I could make your code work by following the solution provided here:

How to set focus to InputText Element?

Index.razor

@page "/"
@inject IJSRuntime JSRuntime

<EditForm Model="@login" class="card card-body mt-2">
    <div class="form-group row">
        <label for="userid" class="col-sm-2 col-form-label">User ID</label>
        <InputText id="@inputID" class="form-control" @bind- 
             Value="@login.UserID" @onkeyup="(KeyboardEventArgs e) => 
             KeyUpUserIDAsync(e)" />
    </div>
    <div class="form-group row">
        <label for="message" class="col-sm-2 col-form- 
           label">Message</label>
        <InputTextArea id="textarea-message" class="form-control" @bind- 
           Value="@errorMessage" />
    </div>
</EditForm>

@code {
    public class LoginModel
    {
       public string UserID { get; set; }
    }

    public LoginModel login = new();
    public string inputID = "user-id";
    public string errorMessage = null;

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

    async Task KeyUpUserIDAsync(KeyboardEventArgs e)
    {

    }
}

_Host.cshtml

<script>
    function focusElement(id) {
        const element = document.getElementById(id);
        element.focus();
    }
</script>

I ran the application several times, and each time it loads the login input gets focus immediately without need for me to refresh the page.

Jason D
  • 1,863
  • 2
  • 16
  • 30