Chupachar
@Chupachar
front-end dev

Как правильно вызвать функцию и отрисовать её содержимое в условии цикла без привязки к итерациям?

Всем привет, имеется код в котором прописана небольшая валидация на проверку пустых select. Проверка работает правильно, по клику на кнопку get если хотя бы 1 select пустой, то функция render() не отрабатывает. В данном случае, когда render() отрабатывает, то выводится 2 console.log() скорее всего из-за количества итераций select. Можно ли как то избежать данного поведения? У меня в проекте, условно в функции render(), рендерится карточка и на данный момент выводится две карточки по клику на кнопку get, хотя мне нужна одна. Подскажите пожалуйста.

https://jsfiddle.net/acqogd2f/2/

<div class="parent">
  <div class="child">
    <select class="select">
      <option value="" selected disabled>List</option>
      <option value="1">1</option>
      <option value="2">2</option>
    </select>
    <select class="select">
      <option value="" selected disabled>List</option>
      <option value="1">1</option>
      <option value="2">2</option>
    </select>
    <button class="button">get</button>
    <div class="error"></div>
  </div>
</div>

<button class="add">add select</button>
<div class="info"></div>

<div class="card"></div>


const button = document.querySelector('.button')
const parent = document.querySelector(".parent")
const error = document.querySelector('.error')
const select = document.querySelectorAll('.select')
const card = document.querySelector('.card')

//клик на get
parent.addEventListener('click', function(e) {
  if (e.target.classList.contains("remove")) {
    e.target.parentNode.remove();
    return
  }
  if (!e.target.classList.contains('button')) return
  let parentBlock = e.target.closest('.parent')
  let childBlock = parentBlock.querySelectorAll('.select')
  let ok = true
  childBlock.forEach((opt) => {
    let option = opt.options[opt.selectedIndex];
    if (option.disabled) {
      opt.classList.add("input-error");
      ok = false
    } else if ([...document.querySelectorAll('.select')].every(x => x.value)) {
      opt.classList.remove("input-error");
      render() //должно выводиться в соответствии с количеством узлов child, а не итераций по select
    } else {
      card.innerHTML = ''
    }
  });
  error.innerHTML = ok ? "" : 'Выберите информацию из выпадающих списков'

  function render() {
    console.log('render')
  }
})


//клик на add select
const child = document.querySelector(".child")
const add = document.querySelector(".add")

add.addEventListener("click", function() {
  child.insertAdjacentHTML(
    "afterend",
    `<div class="child">
                <select class="select">
               <option value="" disabled selected>List</option>
               <option value="3">3</option>
               <option value="4">4</option>
            </select>
            <select class="select">
               <option value="" disabled selected>List</option>
               <option value="5">5</option>
               <option value="6">6</option>
            </select>
        <span class="remove">X</span>
        </div>`
  );
});
  • Вопрос задан
  • 64 просмотра
Пригласить эксперта
Ответы на вопрос 1
@alexalexes
Вы назвали переменную childBlock, а выбираете в нее все узлы - все выпадающие списки всех child.
let childBlock = parentBlock.querySelectorAll('.select');

Тогда уж делайте вложенный перебор. В этом случае будет понятно, на каком уровне foreach какие проверки вставлять.
let childBlocks = parentBlock.querySelectorAll('.child');
childBlocks.forEach(child) =>
{
// контекст одного элемента child
  let childSelects = child.querySelectorAll('.select');
  childSelects.forEach((select) =>
  {
   // контекст одного элемента select
  ...
   // конец контекста одного элемента select
  });
// конец контекста одного элемента child
});

Точнее, вообще не так.
Зачем вы выбираете селекты из всего parentBlock, когда нужен контекст текущей карточки.
Селекты по текущей карточкe, в которой кликнули get, можно получить так:
let childSelects = e.target.querySelectorAll('.select');
 childSelects.forEach((select) =>
  {
   // контекст одного элемента select
  ...
   // конец контекста одного элемента select
  });
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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