Ycon
Ycon

Reputation: 1950

Autofocus input on mount (Vue)- iOS

I would like to trigger the input box to focus (and thus keyboard to pop up) when a Vue component appears.

It does not to work on iOS.

I tried using Vue's example directive (here), and HTML5 autoFocus but neither worked.

I created this example in a sandbox (https://codesandbox.io/s/lw321wqkm).

FWIW, I do not believe it is a JS limitation, as I've seen example work (such as React Native Web using autoFocus- see example)

Parent component

<template>
<div>
  <TextComp v-if='showText' />
  <button @click='showText = !showText'> Show/hide input </button>
</div>
 
</template>
 ...
 

Child component

<template>
<div>
   <input ref='focusMe' type='text'/>
</div>
 
</template>
 
<script>
 
export default {
  name: 'TextComp',
  mounted () {
    this.$refs.focusMe.focus()
  }
}
 
</script>

Upvotes: 16

Views: 29849

Answers (6)

Debu Shinobi
Debu Shinobi

Reputation: 2572

I hope you must have found a solution by now.

But I just wanted to add this for other new users like me.

mounted () {
    this.$refs.focusMe.focus()       // sometime this doesn't work.
  }

Try adding this instead.

this.$nextTick(() => this.$refs.focusMe.focus())

For more info check this

Edit: 14/06/2022

Prashant's answer also helped me understand the nextTick in more depth.

nextTick allows you to execute code after you have changed some data and Vue.js has updated the virtual DOM based on your data change, but before the browser has rendered that change on the page.

Upvotes: 32

Wang Sheng
Wang Sheng

Reputation: 780

https://v2.vuejs.org/v2/guide/custom-directive.html

In vue's official guide it says auto focus does not work in mobile safari. When the page loads, that element gains focus (note: autofocus doesn’t work on mobile Safari).

In iOS mobile safari, focus() only works when responding to a user interaction, like a click event. See: Mobile Safari: Javascript focus() method on inputfield only works with click?

My guess why it does not work in Vue:

In your Vue example, when you click on the button, it merely inserts a watcher into a batcher queue. A watcher has the information about what needs to update. You can see it as an update action, or update event. And later (almost immediately, at the next tick), Vue reads it (watcher) from the queue, and update the virtual dom / dom subsequently. However, this means, your code focus() is not "inside" a click event handler, rather, it is executed after the click event handler finishes.

I don't know the internal implementation of React though, so cannot explain why it works in the React example.

Upvotes: 0

kusiaga
kusiaga

Reputation: 695

I would go with this solution and it works for me. Just add set timeout and put focus method inside it

<template>
   <div>
     <input ref='focusMe' type='text'/>
   </div>

</template>

<script>

export default {
  name: 'TextComp',
  mounted () {

    setTimeout(() => {
       this.$refs.focusMe.focus();
    }, 500);

  }
}

</script>

EDIT:

Ideally you can use $nextTick to wait until the DOM fully loaded, but sometimes it didn't work. So using setTimeout is just quick workaround to me.

Upvotes: 1

Parth Developer
Parth Developer

Reputation: 1867

Still focus doesn't works for you???

Here is the solution :

setTimeout(() => {
  this.$refs["input-0"].focus();
}, 1000);

The trick is to use setTimeout.

Upvotes: -2

jakob
jakob

Reputation: 11

I would suggest triggering a click event on that field instead of focus

this.showText = !this.showText;
this.$nextTick(function () {
    this.$refs.dummykeyboard.click();
})

Upvotes: 0

Felix Jr
Felix Jr

Reputation: 452

You can create a fake input field and focus it during the click event.

<template>
   <div>
     <TextComp v-if='showText' />
     <button @click='onShowText'> Show/hide input </button>
     <input type="text" ref="dummykeyboard" style="opacity:0">
   </div>

</template>
<script>

export default {
  methods:{
    onShowText() {
      this.showText = !this.showText;
      this.$refs.dummykeyboard.focus();
    }
  }
}

</script>

Upvotes: 0

Related Questions