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 + '">' +
我正在尝试使用 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 + '">' +