简体   繁体   中英

Setting focus of an input element in vue.js

I'm trying to set the focus of an input element in Vue.js. I found some help online but none of the explanation worked for me.

Here's my code :

<template>
    <form method="post" action="" v-on:submit.prevent="search">
        <input type="text" placeholder="Person name" required v-model="name" v-el="nameInput" />
        <input type="text" placeholder="Company" required v-model="company" v-el="domainInput" />
        <input type="submit" value="Search" class="btn show-m" />
    </form>
</template>

<script>
export default {
    data () {
        return {
            contacts: [],
            name: null,
            company: null
        }
    },
    ready: {
        // I tried the following :
        this.$$.nameInput.focus();
        this.$els.nameInput.focus();
        // None of them worked !
    }
    methods: {
        search: function (event) {
            // ...

            // I also would like to give the focus here, once the form has been submitted.
            // And here also, this.$$ and this.$els doesn't work
        },
    }
}
</script>

I tried this.$$.nameInput.focus(); and this.$els.nameInput.focus(); for what I could find online to target the focus, but this.$$ is undefined, and this.$els is empty.

If that can help, I'm using vue.js v1.0.15

Thank you for your help.

In vue 2.x you can solve it with a directive .

Vue.directive('focus', {
    inserted: function (el) {
        el.focus()
    }
})

Then you can use v-focus attribute on inputs and other elements:

<input v-focus>

Another solution using Vue 2.x and ref .

You can use the ref/$refs attribute to target your input and focus it.

In the example a simple method is used which can target the inputs using the ref attribute supplied to the inputs. Then access the $refs property on your instance to get a reference to the DOM element.

<script>
export default {
    // ...
  mounted: function () {
    this.focusInput('nameInput');
  },
  methods: {
    // This is the method that focuses the element
    focusInput: function ( inputRef ) {
      // $refs is an object that holds the DOM references to your inputs
      this.$refs[inputRef].focus();
    },

    search: function (event) {
      this.focusInput('domainInput');
    },
  }
}
</script>
<template>
  <form method="post" action="" v-on:submit.prevent="search">
    <input type="text" placeholder="Person name" required v-model="name" ref="nameInput" />
    <input type="text" placeholder="Company" required v-model="company" ref="domainInput" />
    <input type="submit" value="Search" class="btn show-m" />
  </form>
</template>

This solution is best for a one off situation or for a reusable component. For a more global approach the directive is the way to go.

Setting focus inside a child element

(for those of you that struggled for hours like me)

Parent:

<template>
  <div @click="$refs.theComponent.$refs.theInput.focus()">
    <custom-input ref="theComponent"/>
  </div>
</template>

Child ( CustomInput.vue ):

<template>
  <input ref="theInput"/>
</template>

There are a couple of issues.

First of all, v-el s are defined like this:

<input v-el:input-element/>

That'll turn the variable to a camelCase in the code. You can read up more on this weird functionality here .

Other than that, you should be able to access the variable through this.$els.inputElement . Mind you, it will only appear in the component that you're defining that element (or the main app itself, if you defined it there).

Secondly , the automatic focusing does not seem to be working on Firefox (43.0.4), at least on my machine. Everything works great on Chrome, and focuses as expected.

Using ref I managed to focus an Input on mounted like this.

Template :

 <b-form-input  v-model="query" ref="searchInput" ></b-form-input>

Javascript :

  mounted(){
    this.$refs.searchInput.$el.focus()
  }

Vue 3.x

Use a custom directive.

app.directive('focus', {
    mounted(el) { 
      el.focus() 
    }
})

Here is how you use it:

Step 1:

// main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)

 app.directive('focus', {
     mounted(el) { // When the bound element is inserted into the DOM...
       el.focus() // Focus the element
     }
 })

/* Optional: 
   Add a slight delay if the input does not focus.

app.directive('focus', {
    mounted(el) { // When the bound element is inserted into the DOM...
        setTimeout(() => {
            el.focus() // Focus the element
        }, 500)
    }
}) */

await router.isReady()
app.mount('#app')

Then in your component:

Step 2:

// MyInput.vue

<input v-focus>

Vue docs

According to vue 2.x, you can also register "directive" locally in component to get autofocus.

just write directive in component:

export default {
  directives: { focus: {
    inserted: function (el) {
    el.focus()
    }
  }
  }
}

Then in a template, you can use the new v-focus attribute on any element, like this:

<input type="text" v-focus>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM