Skip to content

Alpine.js: How to make ref element visible and focus on click?

When I press on the link “Hallo”, I want that the link “Okay” is visible and focused. However, when I click on “Hallo”, the “Okay” link will become visible, but its not focused. Only if I click again the link “Okay” will be focused. How can I achieve it with to show and focus the link with one click?

  a:focus{
      color:yellow;
    }
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<div x-data="{open:false}">
  <a href="#" @click="open=true;$refs.foo.focus()" >Hallo</a>
  <div x-show="open">
    <a href="#" x-ref="foo">Okay</a>
  </div>
</div>

Answer

When your JS is executed, the foo element is not shown yet, so it cannot be focused. You need to wait for it to be shown before focusing it. $nextTick allows you to do just that:

$nextTick is a magic property that allows you to only execute a given expression AFTER Alpine has made its reactive DOM updates. This is useful for times you want to interact with the DOM state AFTER it’s reflected any data updates you’ve made.

a:focus{
  color:yellow;
}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<div x-data="{open:false}">
  <a href="#" @click="open=true;$nextTick(() => { $refs.foo.focus(); });" >Hallo</a>
  <div x-show="open">
    <a href="#" x-ref="foo">Okay</a>
  </div>
</div>

Is it possible to pass $nextTick to a function and call it there? Or can I only call it inline?

You can add a myMethod property to x-data, and access everything through this:

const appData = {
  open: false,
  myMethod() {
    this.open = true;
    this.$nextTick(() => { this.$refs.foo.focus(); });
  }
};
a:focus {
  color: yellow;
}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<div x-data="appData">
  <a href="#" @click="myMethod">Hallo</a>
  <div x-show="open">
    <a href="#" x-ref="foo">Okay</a>
  </div>
</div>