Tarvo Mäesepp
Tarvo Mäesepp

Reputation: 4533

Selecting div element with arrow keys in Vue

I am trying to navigate through the div elements using arrow keys. I know how to achieve it in JavaScript however I am struggling doing it "vue way". i know there should not be any differences but it simply does not work.

I have made sandbox for you to check what is going on. It is working if I am not using Vue

In Vue I get the following error because of this line:

Cannot read property 'focus' of null

document.activeElement.parentNode.previousSibling.firstChild.focus();

Can anybody tell me what I am doing wrong? Is the v-for the error source or are there some other problems?

Upvotes: 2

Views: 9945

Answers (2)

Stephan-v
Stephan-v

Reputation: 20329

Why not take a data-driven approach to this?

You have an array of items. You can set an active property on each item and toggle that to true or false.

Your up and down keys will change the array pointer and set the current pointer item to true. This way you do not have to do any DOM selection.

Upvotes: 1

A. L
A. L

Reputation: 12669

It really depends on why you need a focus. If it's just to highlight something, you can use a secondary variable to track which one you're currently highlighting and add a class to it instead

https://codesandbox.io/s/300vxzkyk5

<template>
  <div>
    <input ref="input" type="text" @keydown="test" tabindex="0">
    <div ref="test" v-for="item, index in items" :class="{ focus: index === focus }">
       <div>{{ item.title }}</div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { title: "First" },
        { title: "Second" },
        { title: "Third" }
      ],
      focus: null
    };
  },
  methods: {
    test: function(event) {
      switch (event.keyCode) {
        case 38:
          if (this.focus === null) {
            this.focus = 0;
          } else if (this.focus > 0) {
            this.focus--;
          }
          break;
        case 40:
          if (this.focus === null) {
            this.focus = 0;
          } else if (this.focus < this.items.length - 1) {
            this.focus++;
          }
          break;
      }
    }
  }
};
</script>

<style>
div.focus {
  border: 1px solid blue;
}
</style>

Upvotes: 9

Related Questions