Как по клику на кнопку add all id вывести именно те id, по которым кликнул пользователь?

Всем привет, в задаче имеется родительский блок <div class="parent-block">...</div> имеющий в себе определенное количество дочерних блоков <div class="child-block">...</div> в свою очередь в каждом дочернем блоке находятся item с data-id. Задача заключается в том, что мне нужно получить только "кликнутые" data-id определенного родительского блока при нажатии на кнопку add all id, например в первом блоке пользователь кликнул по кнопкам 1, 3, 5 и после клика на add all id должно вывести в консоль 1, 3, 5 и т.д. Кнопка add all id собирает айдишки только со своего child-block. Если пользователь накликал в двух блоках child-block кнопки id, то должны вывестись именно те id, которые относятся ко своему child-block. Можно ли как то решить задачу конкретно этим способом? Потому что у меня в работе это основной костяк в котором куча логики содержится.

parentBlock.addEventListener('click', function(e) {
  if (e.target.classList.contains('btn-all')) {...}})

Сам код:

<div class="parent-block">
  <div class="child-block" id="11">
    <div class="item">
      <span class="elem" data-id="1">1</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="2">2</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="3">3</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="4">4</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="5">5</span>
      <button class="btn">id</button>
    </div>
    <button class="btn-all">add all id</button>
  </div>
  <div class="child-block" id="12">
    <div class="item">
      <span class="elem" data-id="6">6</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="7">7</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="8">8</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="9">9</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="10">10</span>
      <button class="btn">id</button>
    </div>
    <button class="btn-all">add all id</button>
  </div>
</div>
let parentBlock = document.querySelector('.parent-block')
let item = document.querySelector('.item')
parentBlock.addEventListener('click', function(e) {
  if (e.target.classList.contains('btn-all')) {
    [...elem].filter(item => console.log(item.dataset.id))
  }
})


Ответы (1 шт):

Автор решения: highpassion

Здесь вам пригодится проход методом forEach по списку всех DOM-элементов, подходящих по селектору, собранных с помощью метода querySelectorAll(). querySelector находит лишь первое совпадение с селектором, а не все элементы. Повесить слушатель событий надо не .parent-block, а .child-block, поскольку самый верхний элемент содержит обе кнопки, а .child-block лишь свою. Фильтрацию кликнутых элементов я делаю благодаря выбору по селектору, но выбор произвожу методом querySelector() у элемента, а не у всего document для того, чтобы найти лишь вложенные .item элементы у конкретного .child-block. Я использую присваивание класса clicked для обозначения кликнутого элемента, используя метод toggle(), который берет в аргумент название класса и срабатывает как добавление класса, если его нет, или как удаление класса, если он есть.

Переменные, которые я не планирую переназначать я объявляю через const, поскольку так будет легче понимать код как минимум другим разработчикам.

Лично предпочитаю вешать обработчик на саму кнопку и проводить дальшейшие манипуляции вместо определения event.target, но написал под ваш код.

Справка по element.toggle()

Справка по forEach для NodeList

Справка по const

const childBlock = document.querySelectorAll('.child-block')
const item = document.querySelectorAll('.item');

item.forEach( function(e){
  e.addEventListener('click', function(){
    this.classList.toggle('clicked');
  });
});

childBlock.forEach( (a) => {

  a.addEventListener('click', function(e) {
    if (e.target.classList.contains('btn-all')) {

      const thisChildren = this.querySelectorAll('.clicked');
      thisChildren.forEach( (el) => {
         console.log(el.querySelector('.elem').dataset.id);
      });
    }
  })

});
.clicked {
  background: red;
}
<div class="parent-block">
  <div class="child-block" id="11">
    <div class="item">
      <span class="elem" data-id="1">1</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="2">2</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="3">3</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="4">4</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="5">5</span>
      <button class="btn">id</button>
    </div>
    <button class="btn-all">add all id</button>
  </div>
  <div class="child-block" id="12">
    <div class="item">
      <span class="elem" data-id="6">6</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="7">7</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="8">8</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="9">9</span>
      <button class="btn">id</button>
    </div>
    <div class="item">
      <span class="elem" data-id="10">10</span>
      <button class="btn">id</button>
    </div>
    <button class="btn-all">add all id</button>
  </div>
</div>

→ Ссылка