Home > Software engineering >  How can i switch my cursor by using arrow keys when i have multiple input fields in Vuejs
How can i switch my cursor by using arrow keys when i have multiple input fields in Vuejs

Time:02-04

enter image description here

I have a total of 5 textfields made by using v-text-field. i have give autofocus to textfield 3. how can i change my cursor position in other text fields with the help of arrow keys. i have provided the code below which gives the output of the below image but there is no movement of the cursor when we hit arrow keys.

<script>
export default {
  data() {
    return {
      currentItem: 3,
    };
  },
  mounted() {
    document.addEventListener("keyup", this.nextItem);
  },
  methods: {
    nextItem(event) {
      if (event.keyCode == 38 && this.currentItem > 1) {
        this.currentItem -= 2;
      } else if (event.keyCode == 40 && this.currentItem < 6) {
        this.currentItem  = 2;
      } else if (event.keyCode == 37 && this.currentItem < 6) {
        this.currentItem -= 1;
      } else if (event.keyCode == 39 && this.currentItem < 6) {
        this.currentItem  = 1;
      }
    },
  },
};
</script>
<template>
  <div>
      <v-container>
        <div @keyup="nextItem">
          <v-row>
            <v-col cols="12" align-self="center">
              <v-text-field  label="1st" id="1"></v-text-field>
            </v-col>

            <v-col cols="12" sm="6" md="3">
              <v-text-field
                
                label="2nd"
                id="2"
                placeholder="Placeholder"
              ></v-text-field>
            </v-col>
            <v-col cols="12" sm="6" md="3">
              <v-text-field
                
                autofocus
                label="3rd"
                id="3"
                placeholder="Placeholder"
              ></v-text-field>
            </v-col>
            <v-col cols="12" sm="6" md="3">
              <v-text-field
                
                label="4th"
                id="4"
                placeholder="Placeholder"
              ></v-text-field>
            </v-col>
            <v-col cols="12" align-self="center">
              <v-text-field  label="5th" id="5"></v-text-field>
            </v-col>
          </v-row>
        </div>
      </v-container>
  </div>
</template>

CodePudding user response:

that requires manual DOM interaction to me.

set a ref on each field:

<v-text-field ref="first />

Accessing it via this.$refs.first will return you the component instance.

Accessing the component element via this.$refs.first.$el will return you the <div> containing the whole component's element (not the exact template but you get the point):

<div >
  <div>
    <div>
      <input>
    </div>
  </div>
</div>

You only want the input. You can do:

const input = this.$refs.first.$el.querySelector('input')

Or, since Vuetify already set a ref for the input, you can just do:

const input = this.$refs.first.$refs.input

Then just focus it yourself:

input.focus()

Alternatively, you can also try calling the focus method declared on <VTextField>:

this.$refs.first.focus();

Docs regarding $refs and $el: https://vuejs.org/v2/api/#Instance-Properties

Vuetify source code reference for VTextField's $refs.input: https://github.com/vuetifyjs/vuetify/blob/v2.6.3/packages/vuetify/src/components/VTextField/VTextField.ts#L415

Vuetify source code reference for VTextField's focus method: https://github.com/vuetifyjs/vuetify/blob/v2.6.3/packages/vuetify/src/components/VTextField/VTextField.ts#L247

CodePudding user response:

You need to interact with the DOM focus event to change the active focus, I add a ref to each input with the name of input-${id}.

On keyup I check the key events and if that input ref exist I change the currentItem property, with that you can remove the >1 and <6 conditionals.

Because you want to change the focus every time the currentItem variable changes, I add a watcher with immediate true removing the unmounted.

Code Example

Template

<v-container>
  <div @keyup="changeFocusInput">
    <v-row>
      <v-col cols="12" align-self="center">
        <v-text-field
          
          label="1st"
          id="1"
          ref="input-1"
        ></v-text-field>
      </v-col>

      <v-col cols="12" sm="6" md="3">
        <v-text-field
          
          label="2nd"
          id="2"
          ref="input-2"
          placeholder="Placeholder"
        ></v-text-field>
      </v-col>
      <v-col cols="12" sm="6" md="3">
        <v-text-field
          
          autofocus
          label="3rd"
          id="3"
          ref="input-3"
          placeholder="Placeholder"
        ></v-text-field>
      </v-col>
      <v-col cols="12" sm="6" md="3">
        <v-text-field
          
          label="4th"
          id="4"
          ref="input-4"
          placeholder="Placeholder"
        ></v-text-field>
      </v-col>
      <v-col cols="12" align-self="center">
        <v-text-field
          
          label="5th"
          id="5"
          ref="input-5"
        ></v-text-field>
      </v-col>
    </v-row>
  </div>
</v-container>

JS

data() {
    return {
        currentItem: 3,
    };
},
watch: {
    currentItem: {
        handler(value, oldValue) {
        if (value !== oldValue) {
        this.focusInput(value);
        }
        },
        immediate: true
    }
},
methods: {
    getInput(id) {
        const input = this.$refs[`input-${id}`];
        return input;
    },
    changeFocusInput(event) {
        const key_code = {
            left: 37,
            up: 38,
            right: 39,
            down: 40
        };
        
        let nextItem = this.currentItem;
        if (event.keyCode == key_code.up) {
            nextItem -= 2;
        } else if (event.keyCode == key_code.down) {
            nextItem  = 2;
        } else if (event.keyCode == key_code.left) {
            nextItem -= 1;
        } else if (event.keyCode == key_code.right) {
            nextItem  = 1;
        }
        
        if (this.getInput(nextItem)) {
            this.currentItem = nextItem;
        }    
    },
    focusInput(id) {
        const input = this.getInput(id);
        if (input) {
            input.focus();
        }
    },
},
  •  Tags:  
  • Related