Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vuejs: Trying to focus the input using v-el directive

Tags:

vue.js

I am creating a wizard login form where the Mobile Number is first entered and password is entered next.

Here am trying to focus the password input using

this.$$.passwordInput.focus()

however if am getting the error given below

Uncaught TypeError: Cannot read property 'focus' of undefined

The full code is below

index.html

<div id="login">
  <div v-if="flow.mobile">
    <form v-on="submit: checkmobile">
        <p>
          Mobile Number<br>
          <input type="text" v-model="mobile_number" v-el="mobileNumber">
        </p>
    </form>
  </div>
  <div v-if="flow.password">
    <form v-on="submit: checkpassword">
        <p>
          Password<br>
          <input type="password" v-model="password" v-el="passwordInput">
        </p>
    </form>
  </div>

script.js

var demo = new Vue({
el: '#login',
data: {
    flow: {
        mobile: true,
        password: false
    }
},
methods: {
    checkmobile: function(e) {
        e.preventDefault();
        this.flow.mobile = false;
        this.flow.password = true;
        this.$$.passwordInput.focus();
    },
    checkpassword: function(e) {
        e.preventDefault();
    }
}

});

like image 737
Anish Dcruz Avatar asked Jun 16 '15 06:06

Anish Dcruz


People also ask

How do you focus an element in Vue?

Here, we wrap our call to focusInput inside of a nextTick . Using nextTick will allow us to wait until the input is rendered in the DOM. Once it's there, then we can grab it, and focus on it. You can read more about using nextTick on the docs.

What does $t mean in Vue?

Vuex is a state management pattern for vue. js. $t is the injected method from vue. js or Vue. i18n.

What is $refs in Vue?

Refs are Vue. js instance properties that are used to register or indicate a reference to HTML elements or child elements in the template of your application. If a ref attribute is added to an HTML element in your Vue template, you'll then be able to reference that element or even a child element in your Vue instance.

What is $El in Vue?

The $el option in Vue provides Vue with an existing HTML element to mount the Vue instance generated using the new keyword. this. $el. querySelector is used to access HTML elements and modify the element's properties.


5 Answers

Your passwordInput is inside a v-if block, which only gets rendered when you set flow.password to true; However Vue uses asynchronous rendering, so the v-if block will not be rendered immediately. You can use Vue.nextTick to wait until it does:

this.flow.password = true;
var self = this;
Vue.nextTick(function () {
  self.$$.passwordInput.focus();
});

Read the guide about async rendering for more details.

like image 148
Evan You Avatar answered Oct 22 '22 12:10

Evan You


In Vue.js 2.x you can create your own directive to focus a field automatically:

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

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

<input v-focus>

Working example: https://jsfiddle.net/LukaszWiktor/cap43pdn/

like image 35
Lukasz Wiktor Avatar answered Oct 22 '22 11:10

Lukasz Wiktor


If you are using vuejs 2, you should read this:

https://v2.vuejs.org/v2/guide/migration.html#v-el-and-v-ref-replaced

--

In this case, in your template:

use ref="passwordInput" instead v-el="passwordInput"

and in your method:

this.$refs.passwordInput.focus()

I hope this help you!

like image 11
Sebastián Lara Avatar answered Oct 22 '22 13:10

Sebastián Lara


Glad this worked for some of you. I have no idea why, but after trying every conceivable variation of the accepted answer I could not get the $$.ref property when using v-repeat. I could only access the newly created dom elements like so:

new Vue({
el: '#reporting_create',
data: {
    recipients: {
        0: {
            fname: null,
            lname: null,
            email: null,
            registration: false,
            report: false
        }
    },
    curRec:1
},
methods: {
    addRecipient: function(){
        event.preventDefault();
        this.recipients.$add(
            this.curRec,
            {
                fname: null,
                lname: null,
                email: null,
                registration: false,
                report: false
            }
        );
        var num = this.curRec;
        this.$nextTick(function () {
            console.log(this._children[num].$$.rowrec);
            newSwitches.find('.switch').bootstrapSwitch();
        })

        this.curRec++;
    }
}})

html:

<template v-repeat="recipients">
        <div class="row" v-el="rowrec">
            <div>{{$key}}</div>
        </div>
</template>

The addRecipients function was called outside the v-repeat so even the suggested answer here did couldn't help

Not sure if there is an issue with doing it this way but it works and I'm tired.

like image 1
Roark Avatar answered Oct 22 '22 11:10

Roark


Vue.js 1 works a bit different.

Example:

  <textarea v-el:model_message></textarea>

JS:

this.$els.model_message.focus();
like image 1
Jamie Avatar answered Oct 22 '22 11:10

Jamie