E
E
Eugene2020-06-23 14:44:00
JavaScript
Eugene, 2020-06-23 14:44:00

How to make push and focus work in Vue JS?

Hello. The problem is that native JavaScript functions in Vue.JS methods do not work.

I'm making my bike, trying to implement a live search, with the ability to select results with the arrows on the keyboard.

I'm trying to implement the ability to switch between list items and Input. So that when the focus is in Inpute, when you press the down arrow on the keyboard, the first element in the list is selected and so on through the list when you press the down arrow. And upon reaching the last element in the list, when you click down, Input should be highlighted again, similarly when you press the up arrow.

The essence of the problem:I cannot add an Input element to an array with elements for which there is a selection in the list. I have already tried to implement this task in different ways, since the push method basically does not work, the following error comes out: "[Vue warn]: Error in v-on handler: "TypeError: this.resultlist.push is not a function"". Code-wise, this appears in the initList method. The collective farm which is further, in the down and up methods, is associated with this error. I'm trying to get around it somehow and created a variable referring to the input element separately, but when I started writing focus in the down and up methods, I got an error: "[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'focus' of undefined"".

What am I doing wrong? Tell me please. Documentation climbed up and down, I guess I didn’t notice something,

I would be grateful for any constructive criticism and code suggestions (in passing), since I'm just learning.
Further HTML code:

<div id="search">
      <form action="/api/search/" method="get" class="form-inline">
        <label class="mr-sm-2 mb-0 sr-only" for="first_name">Название машины</label>
        <input type="text" v-model="keywords" @keyup.down="down" @keyup.up="up" name="name" placeholder="Название машины" id="vsearch-input" autocomplete="off" class="form-control mr-sm-2 mb-2 mb-sm-0" value="<?= $_GET['name']; ?>">
        <button type="submit" class="btn btn-primary mt-2 mt-sm-0">Найти</button>
      </form>
      <div class="list-group" style="position: absolute;" @keyup.down="down" @keyup.up="up">
        <a v-for="(car, i) in results" :href="'/api/vehicle/?id='+car.id" class="align-items-center list-group-item list-group-item-action text-capitalize">
          <span class="badge badge-primary">{{ car.id }}</span>
          {{ car.name }}
          <span class="badge badge-success">{{ car.name_ru }}</span>
          <span class="badge badge-secondary">{{ car.price }}</span>
        </a>
      </div>
    </div>

And JS code:
var search = new Vue({
    el: '#search',
    data: {
        timeoutId: null,
        keywords: null,
        resultlist: [],
        currelement: -1,
        vsearch: document.querySelector('#vsearch-input'),
        results: null
    },
    watch: {
        keywords: function (newKeyword, oldKeyword) {
            clearTimeout(this.timeoutId);
            this.timeoutId = setTimeout(this.sendQuery, 500);
        }
    },
    methods: {
        highlight(text) {
      return text.replace(new RegExp(this.keywords, 'gi'), '<span class="highlighted">$&</span>');
        },
        initlist: function() {
            this.resultlist = document.querySelectorAll('.list-group > a') || [];
            this.resultlist.push(123); // Вот здесь ошибка с push, не добавляет даже 123
            console.log(this.resultlist);
            console.log(this.resultlist.length);
        },
        resetList: function() {
            this.resultlist = [];
        },
        down: function() {
            if(this.resultlist.length == 0) this.initlist();
            this.currelement++;
            if(this.currelement == this.resultlist.length)
            {
                this.currelement = -1;
                this.vsearch.focus();
                return;
            }
            this.resultlist[this.currelement].focus();
            // TODO: добавить к активному элементу класс active
        },
        up: function() {
            if(this.resultlist.length == 0) this.initlist();
            this.currelement--;
            if(this.currelement == -1)
            {
                this.vsearch.focus();
                return;
            }
            this.resultlist[this.currelement].focus();
            // TODO: добавить к активному элементу класс active
        },
        sendQuery: function () {
            sData = { name: this.keywords };
            this.sendPost('/api/search/', sData);
            clearTimeout(this.timeoutId);
        },
        sendPost: function(sendfurl, senddata) {
            axios({
                method: 'post',
                url: sendfurl,
                data: senddata
            })
            .then(response => 
            {
                console.log(response);
                console.log(response.data);
                if(response.data.length) {
                    this.resetList();
                    this.results = response.data;
                }
                else this.results = null;
            })
            .catch(function (error)
            {
                console.log(error);
            });
        }
    }
})

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Arseny, 2020-06-23
@Vagrant0610

Using document.querySelectorAll('.list-group > a')you create a NodeList (as far as I remember), not an array. Accordingly, nothing will come of it.
In Vue, it would be strange, if not, all the necessary JS arsenal works.
Here, in a single example, you can play around, removing document.querySelectorAll('.list-group > a')(ie, creating the actual array).
https://codepen.io/i-am-studio_en/pen/jOWmLry

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question