Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue: How to call .focus() on button click

I only started coding with vue.js yesterday, and I don't know how to "focus" on a textbox without using the "traditional" JS way, which is document.getElementById('myTextBox').focus().

Initially, my textbox is hidden. I have a "Start" button, and when the user clicks on it, the textbox is then displayed, and I want to set the focus there, so to speak. I already tried using ref, but to no avail (see code below).

HTML:

<input id="typeBox" ref="typeBox" placeholder="Type here..." />

Javascript

export default {
  name: 'game',

  methods: {
    startTimer () {
      setTimeout(function () { /* .focus() won't work without this */

        /* ugly and not recommended */
        // document.getElementById('typeBox').focus()

        /* Throws the error: Cannot read property 'typeBox' of undefined */
        this.$refs.typeBox.focus()

        // ... any other options?
          // ...

      }, 1)
    }
  } /* END methods */

} /* END export default */

Does anyone know how to do this? Please help.

UPDATE:

Adding autofocus on input does the trick of focusing right after the page is loaded. But in my app, there is a need to "refocus" on the input field several times without reloading the page, that's why I need a way to call .focus().

like image 954
ITWitch Avatar asked Mar 09 '17 12:03

ITWitch


People also ask

How do you call a component on click of button Vuejs?

Simply use @click (v-on:click) to toggle Bool.

How do you click a button on Vue?

With Vue, you can tie button clicks to functions you want to execute. The formal way to do this is to use the v-on:click attribute, however, Vue has a neat shortcut, @click .

How do I ref a component in Vue?

Referencing DOM Elements in Vue # If we want to reference a DOM element, we can use the ref attribute in Vue. Vue can store references to DOM elements in a property called $ref . The first thing we have to do, is add a ref attribute to the element we want to reference in our Javascript.


2 Answers

Sharing the solution here just in case someone encounters the same problem...

I finally figured this out with the help of a senior programmer. I was also able to eliminate setTimeout along the way, using its vue version nextTick().

The correct JS code:

startTimer () {
    this.$nextTick(() => {

        // this won't work because `this.$refs.typeBox` returns an array
        // this.$refs.typeBox.focus()

        //this one works perfectly
        this.$refs.typeBox[0].focus()

    })
} /* END startTimer */

Explanation:

When I used console.log(this.$refs.typeBox), it returned this array:

enter image description here

That's why for the code to work, it had to be typeBox[0].focus() instead of typeBox.focus().

like image 147
ITWitch Avatar answered Oct 11 '22 13:10

ITWitch


Finally solved the problem without setTimeout, thanks to window.requestAnimationFrame (I don't know why):

startTimer () {
    window.requestAnimationFrame(() => this.$refs.typeBox.focus())
}

It works even for custom component focusing.

like image 40
mcmimik Avatar answered Oct 11 '22 13:10

mcmimik