Focus an input on select change with Alpine.js

11.6k views Asked by At

I have three tabs and three corresponding select options. When I click on a tab I select its corresponding option. I'd like to be able to select an option and focus its corresponding tab. Thanks in advance.

function tabs(){
return{
  select: 'focus-a',
  tabs:[
    {
      name: 'focus-a'
    },
        {
      name: 'focus-b'
    },
        {
      name: 'focus-c'
    }
  ]
}

}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<div
  x-data="tabs()"
>
    <div>
      <template x-for="btn in tabs">
        <input type="button" x-ref="btn.name" x-on:click="select = btn.name" :value="btn.name" />
      </template>
    </div>

    <div>
        <select name="test">
          <template x-for="tab in tabs" x-on:change="buttons.focus()">
            <option :selected="tab.name === select" :value="tab.name" x-text="tab.name"></option>
          </template>
        </select>
    </div>
    
</div>

2

There are 2 answers

0
James On

I got help over on Github. Working code is below with comments. I lost the trail of who actually fixed it for me. It may have been you Hugo?

function data() {
  return {
    activeTab: 0,
    tabs: [
      {
        id: 0,
        title: "tab-1",
        text: "all the text"
      },
      {
        id: 1,
        title: "tab-2",
        text: "all the tab 2 text"
      }
    ]
  };
}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<div class="" x-data="data()">
  <div>
    <template x-for="tab in tabs" :key="tab.id">
      <button x-text="tab.title" @click="activeTab = tab.id; console.log(activeTab)"></button>
    </template>
  </div>
  <div class="">
    <template x-for="tab in tabs" :key="tab.id">
      <p x-text="tab.text" x-show="tab.id === activeTab"></p>
    </template>
  </div>
  <div>
    <select x-model="activeTab" name="" id="" @change="activeTab = $event.target.options[$event.target.selectedIndex].index; ">
      <template x-for="tab in tabs" :key="tab.id">
        <option :key="tab.id" :value="tab.id" :selected="activeTab === tab.id" x-text="tab.title"></option>
      </template>
    </select>
  </div>
</div>

2
Hugo On

What about binding x-ref (:x-ref="btn.name") so that the x-ref and the option.value are the same?

The other issue I found is that the x-on:change was on the template instead of the select, you can then use the $event.target.value to look up the correct $refs value.

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<div
  x-data="tabs()"
>
    <div>
      <template x-for="btn in tabs">
        <input type="button" :x-ref="btn.name" x-on:click="select = btn.name" :value="btn.name" />
      </template>
    </div>

    <div>
        <select name="test" x-on:change="$refs[$event.target.value].focus()">
          <template x-for="tab in tabs" >
            <option :selected="tab.name === select" :value="tab.name" x-text="tab.name"></option>
          </template>
        </select>
    </div>
    
</div>