Prevent DOM elements from being added on every click - javascript

I have the following script which gets DOM elements with a given class, and adds them to an array. It then loops over the array and adds the values to option elements for a SelectControl component in WordPress Gutenberg. I'm able to get the elements into the array into the dropdown, but I'm receiving the following error: Uncaught TypeError: Cannot read property 'appendChild' of null in the console. It also doesn't show the selected option in the select component when selected and duplicates the array options in the dropdown every time an option from the dropdown is selected.
I suspect it may be an execution sequence issue, but not completely sure:
setTimeout(() => {
let headers = [...document.querySelectorAll('.wp-block-heading')].map(item => item.innerText);
const select = document.getElementById('selectheader');
for (let i = 0; i < headers.length; i++) {
let opt = headers[i];
let el = document.createElement('option');
el.textContent = opt;
el.value = opt;
select.appendChild(el);
}
}, 1000);
<SelectControl
value={[headers]}
id="selectheader"
options={[headers]}
onChange={setJumpLink}
/>

It actually needed:
if (select && select.innerHTML) {
select.innerHTML = '';
}
before the loop.

Related

Cannot console.log() textContent from a selected Option Element that was created using a FOR loop in Javascript to populate a list in a Select Element

I have a function that populates a list of option elements into a select element.
function createOptionElements(){
const select = document.querySelector('select');
for(let i=1;i<11;i++){
const option = document.createElement('option');
option.textContent = i;
select.appendChild(option);
}
}
When I select the option value 3 from the select I would like console.log(option.textContent) to output true.
function outputOptionTextContent(){
const option = document.querySelector('option');
if (option.textContent === "3"){
console.log(true);
}
else {
console.log(false);
}
}
When I simply call console.log(option.textContent) I only ever get the first value in the list, which is 1, even If I select a different value.
The reason I am attempting to do this is, I am calling an HTTP GET request on JSON data, the data has name properties, the name properties will be added to the select as options, & I would like to to call a function when a specific name is clicked, so I was thinking of adding a function that looked for the value of textContent and then compared the textContent value to the name in the JSON data, if they match, invoke the function.
The reason behind could be the fact that textContent is not an standard attribute the standard attribute is value also is better if you use the method built in to do it
option.setAttribute(“value”, variableWithValue);
And yes you guessed it correctly if there is a setAttribute there is also a getAttribute
option.getAttribute(“value”);
So the end result should look like this
window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM fully loaded and parsed');
const select = document.querySelector('select');
for(let i=1;i<11;i++){
const option = document.createElement('option');
option.setAttribute(“value”,i);
select.appendChild(option);
}
/// add the select to the document
document.body.appendChild(select);
select.addEventListener("change", (e) => {
const optionSelected = e.target.value;
})
});
document.querySelector only selects the first element if finds. Instead do document.querySelectorAll('option') and it will return a NodeList. With that you can iterate over it and do what you want
edit: ignore above
Add an event listener to your select element for input.
select.addEventListener('input', e => {
let value = select.options[select.selectedIndex].value;
console.log(value);
})

How do you get the value of the selected option from a dynamically created select element?

I have a button to dynamically create select elements, which i created like this:
var units = units_array[0];
//ingredient unit of measurement drop down
var cell3= row.insertCell(2);
var unit_of_measure = document.createElement("select");
unit_of_measure.name = "unit_of_measure_select";
cell3.appendChild(unit_of_measure);
//Create and append the options
for (var i = 0; i < units.length; i++) {
var option = document.createElement("option");
option.value = units[i];
option.text = units[i];
unit_of_measure.appendChild(option);
}
However, when I select it inside (inside a loop from another function) i get this error in the console:
Uncaught TypeError: Cannot read property 'undefined' of undefined
Here is the code i am using to get to the select element which sits inside a table.
var table = document.getElementById('selected_ingredients');
var rowCount = table.rows.length; //empty table has 2 rows (header + something else?)
var cellsCount = table.rows[0].cells.length -1 ; //table width in cells by counting headers minus the last cell (delete)
for (var r = 1; r < rowCount; r++) { //loop through all rows (r) in table
var $ingredient_dict = {}; //initiate dictionary for this ingredient
for (var c = 0; c < cellsCount; c++) { //loop through each cell (c) in row
var $cell = table.rows[r].cells[c];
if ($cell.innerHTML.includes("select")) { //if its is 3rd iteration (3rd cell along = select box)
alert("test");
//not working - undefined value from generated select element
var UOM = $cell.options[$cell.selectedIndex].value;
alert(UOM);
I would like to return the value of the selected option in var UOM. I'm relatively new to js so apologies if this is simple.
in your if statement you can grab a handle to the select element:
$select = $cell.querySelector('select');
//then to grab the option and value
var UOM = $select.selectedOptions[0].value;
alert(UOM);
I would also recommend that in your if statement instead of checking for text in the innerHTML you:
$cell.querySelector('select');
This will return null which is the equivalent of false if no select element is present, but return true when an element is present. The advantage is that if one of the cells contains the word 'select' for whatever reason if you are checking for the string 'select' it will return true and try to select the element that does not exist, however if you are looking for an element you just found it. Hope this helps.

How to change the selectIndex of a selectBox in an HTMLCollection?

I'm trying to reset the values of all the selectBoxes on my page. The event in question is happening in an onClick so everything is loaded in the DOM.
I have obtained an HTMLCollection of selectBoxes via var selectBoxes = document.getElementsByClassName("selectBox"); I would like to now change the selectIndex of each of those selectBoxes to 0.
However, every time I try to access a property of a specific object from the HTMLCollection, I end up with an undefined value.
selectBoxes.item(0).selectedIndex = undefined
selectBoxes[0].selectedIndex = undefined
var selectBoxes = document.getElementsByClassName("filterBox");
console.log(selectBoxes); //a nice JavaScriptObject
for(i = 0; i < selectBoxes.length; i++){
selectBoxes.item(i).selectedIndex = 0;
}
This is a very interesting article on HTMLCollections: https://hackernoon.com/htmlcollection-nodelist-and-array-of-objects-da42737181f9 which seems to be explaining part of my problem.
I was accessing the selectedIndex property incorrectly. It's not a direct property of the selectBox itself but rather it seems to be inside the children of the selectBox.
var selectBoxes = document.getElementsByClassName("filterBox");
for(i = 0; i < selectBoxes.length; i++){
selectBoxes.item(i).children[0].selectedIndex = 0;
}

How to make an Option Object be selected as the Default Value

The following code triggers just before a page is loaded. Now I've managed to fill a select with values. But I'm not sure on how to make the first value to be the deafault selected value.
$(document).on('pagebeforeshow', '#searchpage',
//This function is the whole function that runs when the pagebefore event occurs
function () {
//This reads the universities from the api we created
$.getJSON(AddressAccess + "Home/university/format/json",
function (data) {
//The data is sent back in a collection of objects. We need to extract each object and do relative operations
for (var i = 0; i < data.length; i++) {
var university = data[i];
var SelectDropDown = document.getElementById("searchuniversity");
var NewOption = new Option(university.Name, university.UniverstiyID);
if (i == 1) {
SelectDropDown.add(NewOption, Selected);
} else {
SelectDropDown.add(NewOption);
}
};
});
});
Now if i use SelectDropDown.add(NewOption,Selected); Only one option is made as an option in the select and what I want is to just make the first option being read from my json data to be the default option appearing in the select.
Set selectedIndex of SelectDropDown to 1:
if (i == 1) {
SelectDropDown.add(NewOption);
SelectDropDown.selectedIndex = 1;
}
If you're really talking about the very first option from the options list, selectedIndex should be 0. The options array of a select element is zero based.
[edit] based on your comment:
maybe the select already contains a blank option. Try:
if (i < 1) {
SelectDropDown.options.length = 0;
SelectDropDown.add(NewOption);
SelectDropDown.selectedIndex = 0;
}
Just set the defaultSelected property of the element to true:
var newOption = new Option(university.Name, university.UniverstiyID);
newOption.defaultSelected = true;
Or use the parameters of the Option constructor:
var newOption = new Option(university.Name, university.UniverstiyID, true, true);

how do i set selected in Dojo form.select option

Hi there Dojo developers, I have a drop down form.select, and it has few options, how do set an option to be selected. Say I want to have the third option displayed in the select element. I was looking at the dojo docs and I do not see setSelected() or similar.
Thanks
You need to use displayedValue property in addition to value to set the displayed option. Use something like:
selector.set("displayedValue", "the_text_of_the_option");
or you can search the underlying store of your drop down by using :
selectorStore.fetch({query:{id: value}, onComplete: function (items) {
dojo.forEach(items, function(item){
selector.set("displayedValue", "the_text_of_the_option");
selector.set("value", "the_value_of_the_option");
});
}});
Hope that helps.
I found it, it is selector.attr("value", "the_name_of_the_option");
Thank you, this is true and working. I have tested it. However i discovered my bug: I was creating the options dynamically, and when I set .selected = true as soon as I add it to the selector it changes the sated to the first one being selected.
Or if I apply selector.set("displayedValue", "the_text_of_the_option");
It displays visually the selected one but in fact behind the selected is still the first one does not meter if I change it with the above selector.set. So I solved it by manually creating the selected state. This way when I add it letter id stays in the desired one and changes it accordingly.
Snipped here:
//populate latitude selector
match = false;
optionsArr = [];
for(var i = 0; i < namesLength; i++){
for(var j = 0, len2 = latNames.length; j < len2; j++){
if(fieldNames[i].toLowerCase() == latNames[j]){
for (var a = 0; a < namesLength; a++) {
var option = {};
option.label = fieldNames[i];
option.value = i+"";
if(i==a){
option.selected = true;
}
optionsArr.push(option);
}
match = true;
}
}
}
if(match){
var drop1 = dijit.byId("selectLatitude");
drop1.addOption(optionsArr);
}else{
var drop1 = dijit.byId("selectLatitude");
drop1.addOption(options);//options is an array of options created originally
}

Categories

Resources