Запросите выбор элементов каждый раз, когда частичный загружается Vanilla Javascript в Rails - PullRequest
0 голосов
/ 17 февраля 2020

У меня есть частичное внутри частичного, которое имеет radio button s или check box es. То, что я хочу сделать, это получить переключатель или флажки, которые нажимаются. Теперь изначально, когда страница загружена, я могу получить кнопки, но когда я go до следующей части, я не могу получить новые кнопки. Как я могу получить кнопки нового частичного каждый раз, когда какая-то кнопка нажимается в отдельном js. Если я использую функцию onclick, встроенную в radio button или checkbox, то функция вызывается правильно, но я хочу получить отображаемые элементы в отдельном файле js.

Я пытался использовать window.addEventListener('change'). Если я использую это, то функция не вызывается при первом щелчке, но при последующих щелчках она вызывается столько раз, то есть при втором щелчке функция вызывается один раз, при третьем щелчке функция вызывается дважды и т. Д.

// window.addEventListener('change', () => {
window.addEventListener('DOMContentLoaded', () => {
  if (document.querySelectorAll('[name="question[answer_id]"]').length !== 0) {
    document.querySelectorAll('[name="question[answer_id]"]').forEach((questionAnswerButton) => {
      questionAnswerButton.addEventListener('click', (event) => {
        console.log(event);
        fetchCall(event.target.value);
      });
    });
  }
});

radio_button_partial. html .erb

<%= radio_button_tag 'question[answer_id]',
                                  answer.id,
                                  (user_answer == answer.id),
                                  {
                                    class: 'answer_opt',
                                    // onclick: fetchCall("<%= answer.id %>")
                                  } %>

Здесь, если я раскомментирую функцию onclick, я получу желаемую функциональность. Но что я должен изменить, чтобы получить отображаемые переключатели из отдельного файла js?

1 Ответ

1 голос
/ 17 февраля 2020

Вместо того, чтобы прикреплять слушателя непосредственно к элементам, которые вы хотите использовать для всплытия событий:

document.addEventListener('click', (event) => {
  if (event.target.matches('[name="question[answer_id]"]')) {
    console.log(event);
    fetchCall(event.target.value);
  }
});

Когда событие запускается, оно всплывает в DOM, пока не будет найден обработчик. В отличие от прикрепления обработчиков событий непосредственно к элементам, это идемпотент, и обработчик будет работать для элементов, динамически вставляемых в страницу. Он также совместим с turbolinks.

Этот код не должен помещаться в тег сценария или мерзость .js.erb, так как он будет добавлять обработчик каждый раз, когда код выполняется. Поместите его в конвейер активов.

Если fetchCall делает ajax вызов, вы захотите использовать метод устранения неполадок, например, отключение ввода и его повторное включение, когда обещание решен.

document.addEventListener('click', (event) => {
  if (event.target.matches('[name="question[answer_id]"]')) {
    console.log(event);
    // Todo refactor fetchCall so that it returns a promise
    let promise = fetchCall(event.target.value);
    event.target.disabled = true;
    promise.then((successMessage) => {
      event.target.disabled = false;
    });
  }
});
...