@Rivix
Новичок в IT - сфере

Как подружить кастомный dropdown с нативным select?

Есть два списка, первый кастомный dropdown виден только при десктопном варианте, а второй нативный select виден на мобилке. Я заметил, дропдаун на мобилке не линкуется с десктопным. То есть если я выберу какую-то опцию в десктопной версии, перейду на мобилку, то там эта опция не будет выбрана. Так как в форме я буду отправлять значение именно того селекта, который нативный, ему нужно значение, выбранное на кастомной десктопной версии - задавать. Не могу сообразить как это провернуть.
<div class="select__wrapper">
  <select class="what_kind" name="boots">
    <option value="download">Загрузи свой вариант или ...</option>
    <option value="run">Беговые кроссовки</option>
    <option value="basketball">Баскетбольные кроссовки</option>
    <option value="fotball">Футбольные кроссовки</option>
    <option value="everyday">Повседневные кроссовки</option>
    <option value="fitnes">Кроссовки для фитнеса</option>
  </select>
</div>
<div class="select__wrapper-mod">
  <button class="dropdown__button">Загрузи свой вариант или ...</button>
  <ul class="dropdown__list">
    <li class="dropdown__list-item" tabindex="0" data-value="download">Загрузи свой вариант или ...</li>
    <li class="dropdown__list-item" tabindex="1" data-value="run">Беговые кроссовки</li>
    <li class="dropdown__list-item" tabindex="2" data-value="basketball">Баскетбольные кроссовки</li>
    <li class="dropdown__list-item" tabindex="3" data-value="fotball">Футбольные кроссовки</li>
    <li class="dropdown__list-item" tabindex="4" data-value="everyday">Повседневные кроссовки</li>
    <li class="dropdown__list-item" tabindex="5" data-value="fitnes">Кроссовки для фитнеса</li>
  </ul>
  <input type="text" name="select-category" value="" class="dropdown__input-hidden">
</div>

js для кастомного дропдауна:
const btnList = document.querySelector('.dropdown__button');
const dropdownList = document.querySelector('.dropdown__list');
const listItem = dropdownList.querySelectorAll('.dropdown__list-item');
const inputNone = document.querySelector('.dropdown__input-hidden');

btnList.addEventListener('click', function (event) {
  event.preventDefault();
  event.stopPropagation();
  dropdownList.classList.toggle('_visible');
  if (dropdownList.classList.contains('_visible')) {
    btnList.classList.add('_selected');
  } else {
    btnList.classList.remove('_selected');
  }

});

listItem.forEach(function (listItem) {
  listItem.addEventListener('click', function () {
    btnList.innerText = this.innerText;
    inputNone.value = this.dataset.value;
    dropdownList.classList.remove('_visible');
  });
});

document.addEventListener('click', function () {
  dropdownList.classList.remove('_visible');
  btnList.classList.remove('_selected');
});

document.addEventListener('keydown', function (event) {
  if (event.key === 'Tab' || event.key === 'Escape') {
    dropdownList.classList.remove('_visible');
    btnList.classList.remove('_selected');
  }
});

listItem.forEach(function (listItem) {
  listItem.addEventListener('keyup', function (event) {
    if (event.key === 'Enter') {
      btnList.innerText = this.innerText;
      inputNone.value = this.dataset.value;
      dropdownList.classList.remove('_visible');
    }
  });
});
  • Вопрос задан
  • 160 просмотров
Решения вопроса 1
@goshaLoonny
Для начала я эти два фрагмента кода:
listItem.forEach(function (listItem) {
  listItem.addEventListener('click', function () {
    btnList.innerText = this.innerText;
    inputNone.value = this.dataset.value;
    dropdownList.classList.remove('_visible');
  });
});

listItem.forEach(function (listItem) {
  listItem.addEventListener('keyup', function (event) {
    if (event.key === 'Enter') {
      btnList.innerText = this.innerText;
      inputNone.value = this.dataset.value;
      dropdownList.classList.remove('_visible');
    }
  });
});

Советую изменить на эти:
dropdownList.addEventListener('click', (e) => {
  if (!e.target.classList.contains('dropdown__list-item')) return;

  btnList.innerText = e.target.innerText;
  inputNone.value = e.target.dataset.value;
  dropdownList.classList.remove('_visible');
})

dropdownList.addEventListener('keyup', e => {
  if (!e.target.classList.contains('dropdown__list-item')) return;
  if (e.key !== 'Enter') return;

  btnList.innerText = e.target.innerText;
  inputNone.value = e.target.dataset.value;
  dropdownList.classList.remove('_visible');
})

Так как если вы захотите добавить новые элементы в список динамически, вам придется ручками добавлять обработчики им.

То есть если я выберу какую-то опцию в десктопной версии, перейду на мобилку, то там эта опция не будет выбрана. Так как в форме я буду отправлять значение именно того селекта, который нативный, ему нужно значение, выбранное на кастомной десктопной версии - задавать.

Если вы обрабатываете значение из <select>, то зачем вы присваиваете полученное после клика по пункту в кастомном dropdow значение другому элементу?
<input type="text" name="select-category" value="" class="dropdown__input-hidden">

const inputNone = document.querySelector('.dropdown__input-hidden');
/* *** */
inputNone.value = this.dataset.value;

Очевидным решением будет присваивать значение именно <select> который с ваших слов вы обрабатываете в последующем.
<select class="what_kind" name="boots"> *** </select>

const whatKindSlct = document.querySelector('.what_kind');
/* *** */
whatKindSlct.value = this.dataset.value;
// Или 
// whatKindSlct.value = e.target.dataset.value;
// Если решите использовать мой код

P.S. Обратите внимание на повторяющийся код
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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