0

I am trying to learn stencilJS, I am developing the component which has input field with auto focus.

I am calling component twice in index.html, I am getting into strange issue the second render component is taking autofocus of first render component.

And the components are not render on same order every time, the component which renders last it's input field will have the focus remaining will not get autofocus.

Attached code below, please help me to sort out.

index.html

<!DOCTYPE html>
<html dir="ltr" lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" />
    <title>Stencil Component Starter</title>

    <script type="module" src="/build/testing.esm.js"></script>
    <script nomodule src="/build/testing.js"></script>
  </head>
  <body>
    <search-input data-test-id="test-two" place-holder="Search" value=""></search-input>
    <search-input data-test-id="test-three" place-holder="Search" value=""></search-input>
  </body>
</html>

Search-plugin.tsx

import { Component, h, Prop, Event, EventEmitter } from '@stencil/core';
@Component({
  tag: 'search-input',
  styleUrl: 'search-input.css',
  shadow: true,
})
export class SearchInput {
  private searchInput: HTMLInputElement;
  
  @Prop() value = "";
  
  @Prop() dataTestId!: string;
  
  @Prop() placeHolder: string = "Search";
  
  @Event() clearSearch: EventEmitter;
  
  @Event() searchRequest: EventEmitter;

  protected componentDidLoad() {
    this.searchInput.focus();
  }

  render() {
    return (
      <div data-test-id={this.dataTestId} class="items-center flex bg-white border-solid rounded-sm border-gray-300 box-border text-xl border-1 pl-15 pr-12 py-9">
          <input
            type="text"
            ref={el => (this.searchInput = el as HTMLInputElement)}
            data-test-id={`${this.dataTestId}-search-input`}
            class="focus:outline-none border-0 flex-grow w-full pl-15"
            value={this.value}
            placeholder={this.placeHolder}
          />
      </div>
    );
  }
}
MogerCS
  • 342
  • 1
  • 5
  • 16

1 Answers1

0

Two elements - custom elements / web components or standard HTML elements - cannot have focus at the same time. But your code tries to do this - every search-input on the page will try to take focus when the Stencil lifecycle executes componentDidLoad - so that last one rendered by Stencil wins. The order of which is not predictable because Stencil is asynchronous.

If you only want one of the elements to have initial focus, add a property to the component to enable this. For example:

export class SearchInput {
    ...
    @Prop() autoFocus: boolean = false;
    ...
    componentDidLoad() {
        if (this.autoFocus) {
            this.searchInput.focus();
        }
    }
}
<search-input auto-focus data-test-id="test-two" place-holder="Search" value=""></search-input>
<search-input data-test-id="test-three" place-holder="Search" value=""></search-input>
G. Tranter
  • 16,766
  • 1
  • 48
  • 68