skip to Main Content

I have a Blazor server side app with several mainpages. Each mainpage has some subpages which can be entered via buttons. If one subpage is opened in a mainpage, then navigated to another mainpage, and finally navigated back to the same mainpage my last opened subpage is opened as expected. But just one thing is missing: The related subpage button should be re-focused again so that the user can understand in which subpage he is landing.

Therefore I have defined "autofocus" option for each subpage button, and according to the last opened subpage I have just set the related autofocus variable to true (all others to false). But still the related subpage button is not highlighted as defined in the css. What could be the problem?

My razor page code:

 ...
 <button class="icon-button" autofocus="@focus_sub1" @onclick="Function_sub1">sub1                    
 </button>
 <button class="icon-button" autofocus="@focus_sub2" @onclick="Function_sub2">sub2                    
 </button>
 <button class="icon-button" autofocus="@focus_sub3" @onclick="Function_sub3">sub3                    
 </button>
 ...

My razor cs page:

  public bool focus_sub1=false;
  public bool focus_sub2=false;
  public bool focus_sub3=false;
  public string selected_page="";

  protected override void OnInitialized()
  {         
        switch (selected_page)
        {
            case "sub1":
                focus_sub1 = true;
                focus_sub2 = false;
                focus_sub3 = false;
                break;
            case "sub2":
                focus_sub1 = false;
                focus_sub2 = true;
                focus_sub3 = false;
                break;
            case "sub3":
                focus_sub1 = false;
                focus_sub2 = false;
                focus_sub3 = true;
                break;
            default:
                // code block
                break;
        }

  }


  public void Function_sub1 ()
  { 
     selected_page= "sub1"
     // rest code
  }
  public void Function_sub2 ()
  { 
     selected_page= "sub2"
     // rest code
  }
  public void Function_sub3 ()
  { 
     selected_page= "sub3"
     // rest code
  }

My css definition:

/* normal button */
.icon-button{        
    color: black;       
}   

/* highlighted button when subpage selected */
 .icon-button:focus {
    color: blue;
    font-weight: bold;
}

2

Answers


  1. In Blazor, the HTML autofocus works only when the element is first rendered in the DOM. Once the page is loaded, dynamically setting autofocus in blazor alone won’t bring back autofocus to the button, because autofocus is not a re-focusable attribute in html. You’ll need to use JavaScript to focus on the button dynamically. In your wwwroot/index.html add this JS function to focus an element

    <script>
        window.setFocus = function(element) {
            if (element) {
                element.focus();
            }
        }
    </script>
    

    this ought to work

    Login or Signup to reply.
  2. I struggled a little to build a picture of what you’re trying to do, so forgive me if this is wide of the mark.

    Here’s a demo page, using the standard demo template pages that demonstrates how to acquire ElementReference objects for the buttons and use FocusAsync to set the focus to the relevant button.

    @page "/"
    
    <PageTitle>Home</PageTitle>
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <div class="m-2 p-2">
        <button @ref="_counterButton" class="btn btn-primary" @onclick="() => SetComponent(new ComponentData(typeof(Counter), _counterButton))">Counter</button>
        <button @ref="_weatherButton" class="btn btn-danger" @onclick="() => SetComponent(new ComponentData(typeof(Weather), _weatherButton))">Weather</button>
    </div>
    
    <DynamicComponent Type="_currentComponent" />
    
    @code {
        private ComponentData _selectedComponent = default!;
        private ElementReference _counterButton;
        private ElementReference _weatherButton;
        private Type _currentComponent => _selectedComponent.Component ?? typeof(Counter);
    
        // lightweight object to hold the component data
        private readonly record struct ComponentData(Type Component, ElementReference Element);
    
        protected override async Task OnInitializedAsync()
        {
            // Ensure the component renders and the element references are set.
            await Task.Delay(1);
    
            // Set the default selected component
            _selectedComponent = new ComponentData(typeof(Counter), _counterButton);
        }
    
        private Task SetComponent(ComponentData component)
        {
            _selectedComponent = component;
    
            return Task.CompletedTask;
        }
    
        protected async override Task OnAfterRenderAsync(bool firstRender)
        {
            await _selectedComponent.Element.FocusAsync();
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search