querySelector - 无法读取 null 的属性。带有建议的动态表单

querySelector - Cannot read properties of null. Dynamic Form with Suggestions

我正在尝试使用 Javascript 创建一个动态表单,可以在其中添加更多字段。当用户开始在添加的字段中输入时,建议应该基于列表显示。 Suggested inputs based on written input

添加的字段应该与 1 中显示的一样。搜索功能通过使用 querySelector 获取创建的新字段来工作。但是,我收到类型错误:TypeError: Cannot read properties of null.

该功能在没有 newSearch(i) 的情况下也能正常工作,但我希望在添加更多字段时显示此建议框。

源代码:

sites.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;
  }
}

交换这两行应该可以正常工作。在您的情况下,searchWrapper2 为 null。

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

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

添加元素后需要调用newSearch

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

并且您需要删除 innerHTML 中多余的 space,这就是找不到 id 属性的原因,这会破坏所有代码:

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