How to set focus on an input element from an element inside in parent scope (AlpineJS)?

Viewed 29

I am using the latest version of Alpine. I need to set focus on the input searchbox as soon as it become visible. Here is my code for reference.

<div x-data="{search: false}">
   <button x-on:click="search = true">Click to open search box</button>
   <div x-data="searchwidget" x-show="search">
       <input type="search" x-model="term" x-ref="searchInput" />
   </div>
</div>

Data handler for search input

document.addEventListener('alpine:init', () => {
    Alpine.data('searchwidget', () => ({
         term: "",
    }));
});

I tried to put $refs.searchInput.focus() on button element, but its not working.

1 Answers

You have an error at the button: you need to use x-on:click="search = true" or the shorthand syntax: @click="search = true". Furthermore, Alpine.js have an official focus plugin. With this plugin it is very easy to set the focus based on some condition. In your case you just need to put x-trap="search" to the input element, so Alpine.js will set the focus to the input element when search becomes true.

<input type="search" x-model="term" x-trap="search" />

Edit: Without the focus plugin, you need to create a watcher in the init() method and set focus on the input element in the $nextTick() magic property:

<div x-data="{search: false}">
  <button @click="search = true">Click to open search box</button>
  <div x-data="searchwidget" x-show="search">
    <input type="search" x-model="term" x-ref="searchinput" />
  </div>
</div>

<script>
document.addEventListener('alpine:init', () => {
  Alpine.data('searchwidget', () => ({
    term: "",
    init() {
      this.$watch('search', (value) => {
        this.$nextTick(() => {
          if (value) {
            this.$refs.searchinput.focus()
          }
        })
      })
    }
  }));
})
</script>
Related