Найти конкретный div в forEach

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

const $searchField = document.querySelectorAll('.js-search');

if ($searchField.length > 0) {
  $searchField.forEach(function($el) {
    // $el = .js-search
    $el.addEventListener('click', function(event) {
      $el.classList.add('is-active');
    });

    // Here, i need to target the input, not .js-search
    $el.addEventListener('keyup', function(event) {
      if ($el.value.length > 0) {
         $el.classList.add('is-active');
       } else {
         $el.classList.remove('is-active')
       }
    //});
  });
}

Здесь $el относится к родительскому .js-search поэтому очевидно, что keyup не может работать. Я хотел бы убедиться, что выбрал вход, но я не уверен, как это сделать правильно.

Демо доступно на Codepen !

Цель состоит в том, чтобы сохранить состояние активным, когда поиск завершен (имеет по крайней мере 1 символ).

Спасибо

Всего 2 ответа


Просто выберите .value дочернего input вместо $el .value :

const $searchField = document.querySelectorAll('.js-search');
$searchField.forEach(function($el) {
  // $el = .js-search
  $el.addEventListener('click', function() {
    $el.classList.add('is-active');
  });

  const input = $el.querySelector('input');
  input.addEventListener('keyup', function() {
    if (input.value.length > 0) {
       $el.classList.add('is-active');
     } else {
       $el.classList.remove('is-active')
     }
  });
});

Обратите внимание, что нет необходимости в проверке if, если вы не хотите - вызов forEach для пустой коллекции не выдаст ошибку, он просто не будет перебирать что-либо.

Вы также можете подумать о включении полизаполнения для NodeList.prototype.forEach (если вы этого еще не сделали), так как старые браузеры не поддерживают его. (Или же преобразуйте коллекцию в массив или используйте Array.prototype.forEach.call )

Немного основанный на мнении, но нет необходимости ставить префикс имени переменной с $ - это не PHP. Часто префикс $ делается, когда указывается, что что-то является коллекцией jQuery ( $ ). Если вы выполняете манипуляции с DOM, возможно, лучше не использовать имя переменной, начинающееся с $ , чтобы избежать путаницы для будущих читателей вашего кода.


Вы можете использовать this.querySelector('input'); где this будет родительский элемент и querySelector получит первый input дочерний элемент

 const $searchField = document.querySelectorAll('.js-search'); if ($searchField.length > 0) { $searchField.forEach(function($el) { $el.addEventListener('click', function(event) { $el.classList.add('is-active'); let $input = this.querySelector('input'); $input.addEventListener('keyup', function(et) { console.log(et.target.value) }); }); }); document.addEventListener('click', function(event) { if (!$(event.target).closest('.js-search').length) { closeSearchs(); } $('.js-search.is-active').not($(event.target).closest('.js-search')).removeClass('is-active'); }); } function closeSearchs() { $searchField.forEach(function($el) { $el.classList.toggle('is-active'); }); } 
 .field-search { position: relative; &.is-active { .search-input { background-color: rgba(0, 0, 0, .35); color: white; } } .search-input { background: none; box-shadow: none; border-radius: 4px; color: black; font-size: 1.2rem; font-weight: 400; height: 100%; outline: none; padding-left: 4.5rem; transition: background-color .2s; width: 365px; &::placeholder { color: black; font-size: 1.2rem; font-weight: 400; } &.is-active { background-color: rgba(255, 255, 255, .1); } } } 
 <div class="field-search js-search"> <input type="search" class="search-input" placeholder="Search..."> </div>