MDC Web: mdc-select обновляет скрытое входное значение при изменении (нестандартное поле выбора) | JavaScript (JS)

До сих пор у меня все получалось с веб-компонентами MDC, но я слишком долго зависал здесь. (Не силен в JS.)

Раньше mdc-select был ненативным, затем использовался собственный выбор HTML, и теперь он снова не нативный. Некоторое время MDC Web поддерживала скрытый ввод, чтобы вы могли передавать значения на сервер.

Документации почти нет — в основном просто застрявшие пользователи вроде меня, открывающие вопросы на GitHub:

Закрыто: Выбор MDC — больше не совместим с формой ввода #2221

Закрыто: [MDC Select] Пример в README действительно отправляет значения на веб-сервер #5295

Открыть: [MDCSelect] Добавить скрытый элемент ввода для поддержки HTML-форм #5428< /а>

Мне нужно установить/обновить значение скрытого ввода в MDCSelect для нескольких полей выбора на одной странице... Я могу заставить его сделать это для ОДНОГО поля выбора, но не для нескольких.

Вот окно выбора HTML:

<div class="mdc-select mdc-select--outlined region-select">
  <div class="mdc-select__anchor demo-width-class">
    <i class="mdc-select__dropdown-icon"></i>
    <div id="demo-selected-text" class="mdc-select__selected-text" tabindex="0" aria-disabled="false" aria-expanded="false"></div>
    <div class="mdc-notched-outline">
      <div class="mdc-notched-outline__leading"></div>
      <div class="mdc-notched-outline__notch" style="">
        <label id="outlined-label" class="mdc-floating-label" style="">Region</label>
      </div>
      <div class="mdc-notched-outline__trailing"></div>
    </div>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class">
    <ul class="mdc-list">
      <li data-value="" disabled="" aria-selected="false" role="option" class="mdc-list-item" tabindex="0"></li>
      <li data-value="north" aria-selected="false" role="option" class="mdc-list-item" tabindex="-1">North</li>
      <li data-value="east" aria-selected="false" role="option" class="mdc-list-item" tabindex="-1">East</li>
      <li data-value="south" aria-selected="false" role="option" class="mdc-list-item" tabindex="-1">South</li>
      <li data-value="west" aria-selected="false" role="option" class="mdc-list-item" tabindex="-1">West</li>
    </ul>
  </div>
<!-- THIS IS THE HIDDEN INPUT THANK YOU -->
<input type="hidden" id="name2" name="input_name2" value="" class="my_mdc-select__value" />
</div>

Я пытался настроить таргетинг на скрытый ввод с идентификатором, именем и даже классом. Я думаю, мне нужна какая-то интегрированная функция, forEach или цикл - безрезультатно пытался добавить JS под каждый выбор. Я работал с примерами (см. Ниже) от других пользователей и не добился успеха. JavaScript не моя вещь, я знаю, что это должно происходить, но не знаю синтаксиса функций или циклов и т. д., чтобы это работало.

Мне нужно убедиться, что каждый набор/обновление нацелен на правильный скрытый ввод, связанный с этим конкретным полем выбора.

Вот мой JS, который работает для ОДНОГО поля выбора, но не для нескольких:

// Select Menu
import {MDCSelect} from '@material/select';

const selectElements = [].slice.call(document.querySelectorAll('.mdc-select'));

selectElements.forEach((selectEl) => {
  const select = new MDCSelect(selectEl);

 select.listen('MDCSelect:change', (el) => {
    const elText = el.target.querySelector(`[data-value="${select.value}"]`).innerText;

    console.log(`Selected option at index ${select.selectedIndex} with value "${select.value}" with a label of ${elText}`);

    // this works but only saves one
    document.querySelector('input.my_mdc-select__value').value = select.value;
});

}); 

Вот некоторый код, который использовали другие, который я не смог изменить/применить (взято из ссылок выше):

От nikolov-tmw:

document.querySelectorAll( '[data-mdc-auto-init="MDCSelect"]' ).forEach( function( sel ) {
    sel.My_MDCSelect__Value = sel.querySelector('input.my_mdc-select__value');
    if ( null !== sel.My_MDCSelect__Value ) {
        sel.addEventListener( 'MDCSelect:change', function( a ) {
            if ( sel.MDCSelect ) {
                sel.My_MDCSelect__Value.value = sel.MDCSelect.value;
            }
        } );
    }
} );

От daniel-dm:

<div class="mdc-select">
  ...
</div>
<input id="pet-select" type="hidden" name="pets">
<script>
  const input = document.querySelector('#pet-select');
  const select = document.querySelector('.mdc-select');
  select.addEventListener('MDCSelect:change', e => {
    input.value = e.detail.value;
  });
</script>

Пожалуйста помоги! Эта конкретная проблема была открыта с января (люди боролись задолго до этого) без четкого решения, которое помогло бы разработчикам, не использующим JS, реализовать блоки MDCSelect. Заранее спасибо!


person JDizzle    schedule 15.04.2020    source источник
comment
могу я спросить, почему вы используете [].slice.call(document.querySelectorAll('.mdc-select')) , а не просто document.querySelectorAll('.mdc-select')?   -  person I am a registered user    schedule 17.04.2020
comment
@ Я зарегистрированный пользователь Для .mdc-button и .mdc-text-field у меня не было проблем с ручным созданием экземпляров ... но, похоже, это не работает с .mdc-select. При устранении неполадок я нашел [].slice.call здесь: GitHub #3236 и здесь : stackoverflow mdc-textfield-working-but... .. .а почему? Я не могу объяснить, рад узнать, почему я не должен быть! Я могу попробовать еще раз с document.querySelectorAll('.mdc-select')   -  person JDizzle    schedule 20.04.2020
comment
Использовал это: const selectElements = document.querySelectorAll('.mdc-select'); selectElements.forEach(selectElement => MDCSelect.attachTo(selectElement)); Кажется, работает. Работаем над ответом Рустема Гареева ниже.   -  person JDizzle    schedule 20.04.2020
comment
Для тех, кто заинтересован: [].slice.call ака Array.prototype.slice.call — это способ преобразовать NodeList (или любую итерацию в этом отношении) в экземпляр JS Array и использовать все полезные методы встроенного. querySelectorAll возвращает NodeList.   -  person Oleg Valter    schedule 08.09.2020


Ответы (1)


Проблема здесь:

document.querySelector('input.my_mdc-select__value').value = select.value;

Document.querySelector найдет первый соответствующий элемент в весь документ, поэтому в цикле вы всегда обращаетесь к одному и тому же элементу input.

Вместо этого следует запустить метод querySelector для < em>родительский элемент каждого скрытого ввода, который в вашем цикле будет выглядеть так:

selectEl.querySelector('input.my_mdc-select__value').value = select.value;
person Rustem Gareev    schedule 17.04.2020
comment
Спасибо Рустем Гареев! Для тех, кто следит за этим, это работает с ручным созданием экземпляров! // Select Menu import {MDCSelect} from '@material/select'; const selectElements = document.querySelectorAll('.mdc-select'); selectElements.forEach((selectEl) => { const select = new MDCSelect(selectEl); select.listen('MDCSelect:change', () => { selectEl.querySelector('input.my_mdc-select__value').value = select.value; }); }); - person JDizzle; 21.04.2020