Vagrant0610
@Vagrant0610
PHP разработчик

Как заставить работать push и focus во Vue JS?

Здравствуйте. Проблема заключается в том что не работают нативные функции JavaScript в методах Vue.JS.

Я делаю свой велосипед, пытаюсь реализовать живой поиск, с возможность выбора результатов стрелочками на клавиатуре.

Пытаюсь реализовать возможность переключения между элементами списка и Input. Что бы когда фокус находится в Inpute, при нажатии стрелочки вниз на клавиатуре, выделяется первый элемент в списке и так далее по списку при нажатии на стрелочку вниз. И по достижению последнего элемента в списке, при нажатии вниз, должен снова выделяться Input, аналогично и при нажатии стрелочки вверх.

Суть проблемы: не могу добавить в массив с элементами по которым идёт выделение в списке, элемент Input. Пытался уже разными способами реализовать эту задачу, так как метод push в принципе не работает, вылезает такая ошибка: "[Vue warn]: Error in v-on handler: "TypeError: this.resultlist.push is not a function"". По коду это появляется в методе initList. Колхоз который дальше, в методах down и up, связан именно с этой ошибкой. пытаюсь её как-то обойти и создал переменную ссылающуюся на элемент input отдельно, но когда я началь прописывать focus в методах down и up, я получил ошибку: "[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'focus' of undefined"".

Что я делаю не так? Подскажите пожалуйста. Документацию облазил вдоль и поперёк, полагаю что-то не заметил, но не могу понять что именно.

Буду благодарен любой конструктивной критике и предложениям по коду (попутно), так как я только учусь.
Далее HTML код:
<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>

И JS код:
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);
            });
        }
    }
})
  • Вопрос задан
  • 290 просмотров
Решения вопроса 2
ArsenyMatytsyn
@ArsenyMatytsyn Куратор тега JavaScript
Руководитель frontend направления, предприниматель
Используя document.querySelectorAll('.list-group > a') ты создаешь NodeList (насколько я помню), а не массив. Соответственно, из этого ничего не выйдет.

В Vue, странно было бы, если бы не, работают весь необходимый арсенал JS.

Вот в отдельно взятом примере можешь поиграться, убирая document.querySelectorAll('.list-group > a') (т.е. создавая собственно массив).
https://codepen.io/i-am-studio_ru/pen/jOWmLry
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
this.resultlist = [...document.querySelectorAll('.list-group > a')]
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы