QuerySelector - Не удается прочитать свойства null. Динамическая форма с предложениями

Я пытаюсь создать динамическую форму с помощью Javascript, где можно добавить больше полей. И когда пользователь начинает вводить в добавленных полях, предложения должны отображаться на основе списка. Предлагаемые входные данные на основе письменных входных данных

Добавленные поля должны выглядеть точно так же, как показано в 1. Функция поиска работает с использованием querySelector для получения нового созданного поля. Однако я получаю сообщение об ошибке типа: TypeError: Cannot read properties of null.

Функция работает без newSearch(i), но я хочу, чтобы это окно предложения появлялось при добавлении дополнительных полей.

Исходный код:

сайты.html

<div class = "sites-container">
    <form class = "sites-form" method = "POST" id = "myForm" name = "myForm">
        <div class = "wrapper">
          <div id = "Site-options">
            <h1 class = "sites-add-header"> Create a String </h1>
            <p class = "sites-add-text"> Choose Modules at String </p>
            <div class = "wrapper2">
              <div class = "search-input2">
                <a href = "" target = "_blank" hidden></a>
                <input type = "text" placeholder = "Type to search.." name = "PV-modules">
                <div class = "autocom-box2">
                </div>
                <div class = "icon2"><i class = "fas fa-search"></i></div>
              </div>
            </div>
          </div>
        <div class = "controls">
          <a href = "#" id = "add_more_fields"><i class = "fa fa-plus"></i>Add Another String</a>
          <a href = "#" id = "remove_fields"><i class = "fa fa-plus"></i>Remove Site</a>
        </div>
    </div>

    <button type = "submit" class = "sites-add-site button">Add Site</button>
  </form>
</div>

<script>
    let suggestions2 = {{ modules | safe}} ;
</script>
<script src = "{{ url_for('static', filename='add-site.js') }}"></script>>

добавить-site.js


var site_options = document.getElementById('Site-options');
var add_more_fields = document.getElementById('add_more_fields');
var remove_fields = document.getElementById('remove_fields');
var count = 1;
add_more_fields.onclick = function(){
  var i = count++;
  var _div = document.createElement('div');
  _div.setAttribute('id','new-div'+i);
  _div.innerHTML =  '<p class = "sites-add-text"> Choose Modules at Site </p>' + 
                    '<div class = "wrapper2">' +
                      '<div class = "search-input2" id = "new-search-input' + i + ' ">' +
                        '<a href = "" target = "_blank" hidden></a>' +
                        '<input type = "text" placeholder = "Type to search.." name = "PV-modules">' +
                        '<div class = "autocom-box2 id = "new-autocom-box' + i + '">' +
                        '</div>'+
                        '<div class = "icon2" id = "new-icon' + i + '><i class = "fas fa-search"></i></div>'+
                      '</div>'+
                    '</div>';
  newSearch(i);
  site_options.appendChild(_div);
};
remove_fields.onclick = function(){
  var elem = document.getElementById("new-div");
  elem.parentNode.removeChild(elem);
}


function newSearch(i) {
  // getting all required elements
  var searchWrapper2 = document.querySelector("#new-search-input" + i);
  var inputBox2 = searchWrapper2.querySelector("input");  // <- Here i get TypeError
  var suggBox2 = searchWrapper2.querySelector(".autocom-box2");
  var icon2 = searchWrapper2.querySelector(".icon2");
  let linkTag2 = searchWrapper2.querySelector("a");
  let webLink2;
  // if user press any key and release
  inputBox2.onkeyup = (e2)=>{
      let userData2 = e2.target.value; //user enetered data
      let emptyArray2 = [];
      if (userData2){
          icon2.onclick = ()=>{
              webLink2 = `https://www.google.com/search?q=${userData2}`;
              linkTag2.setAttribute("href", webLink2);
              linkTag2.click();
          }
          emptyArray2 = suggestions2.filter((data2)=>{
              //filtering array value and user characters to lowercase and return only those words which are start with user enetered chars
              return data2.toLocaleLowerCase().startsWith(userData2.toLocaleLowerCase());
          });
          emptyArray2 = emptyArray2.map((data2)=>{
              // passing return data inside li tag
              return data2 = `<li>${data2}</li>`;
          });
          searchWrapper2.classList.add("active"); //show autocomplete box
          showSuggestions2(emptyArray2);
          let allList2 = suggBox2.querySelectorAll("li");
          for (let i = 0; i < allList2.length; i++) {
              //adding onclick attribute in all li tag
              allList2[i].setAttribute("onclick", "select2(this)");
          }
      }else{
          searchWrapper2.classList.remove("active"); //hide autocomplete box
      }
  }
  function select2(element){
      let selectData2 = element.textContent;
      inputBox2.value = selectData2;
      icon2.onclick = ()=>{
          webLink2 = `https://www.google.com/search?q=${selectData2}`;
          linkTag2.setAttribute("href", webLink2);
          linkTag2.click();
      }
      searchWrapper2.classList.remove("active");
  }
  function showSuggestions2(list){
      let listData2;
      if (!list.length){
          userValue2 = inputBox2.value;
          listData2 = `<li>${userValue2}</li>`;
      }else{
        listData2 = list.join('');
      }
      suggBox2.innerHTML = listData2;
  }
}

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
44
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

поменяйте местами эти две строки, должно работать нормально. searchWrapper2 в вашем случае имеет значение null.

newSearch(i); site_options.appendChild(_div);

site_options.appendChild(_div); newSearch(i);

аааа, ты прав, что их нужно менять. Однако я все еще получаю то же сообщение об ошибке типа в функции newSearch(i) при чтении "#new-search-input" + i

Søren T 09.05.2022 11:19
Ответ принят как подходящий

вам нужно вызвать newSearch после добавления элемента

site_options.appendChild(_div);
newSearch(i);

и вам нужно удалить лишний пробел в innerHTML, поэтому атрибут id не находит, ломая весь код:

'<div class = "search-input2" id = "new-search-input' + i + '">' +

Другие вопросы по теме