Multiple appendChild calls in the same loop - javascript

listCities.forEach(function(city){
let option = document.createElement('option');
option.value = city;
listFrom.appendChild(option);
listTo.appendChild(option);
});
I have an array and I want to add each string in it as options to two datalists (listFrom and listTo). The problem is that no matter the order I put them, only the last one of the list gets the options added to them.
Is there a way to do this in the same forEach loop or do I have to create two different loops that do exactly the same thing.
I'm just having trouble understanding the logic behind it.

When you appendChild, you MOVE the element to the last mentioned container since the element only exists once in the DOM.
This is a LOT faster than creating an option, cloning it and appending it twice:
const listCities = ["Buenos Aires","Cordoba","Rosario","Mendoza","La Plata","Tucumán","Mar del Plata","Salta","Santa Fe","San Juan","Resistencia","Santiago del Estero","Corrientes","Neuquén","Posadas","San Salvador de Jujuy","Bahía Blanca","Paraná","Formosa","San Fernando del Valle de Catamarca","San Luis","La Rioja","Comodoro Rivadavia","Río Cuarto"],
listFrom = document.getElementById("from"),
listTo = document.getElementById("to");
const options = listCities
.map(city => `<option value="${city}">${city}</option>`)
.join("");
listFrom.innerHTML += options;
listTo.innerHTML += options;
<select id="from"><option value="">From city</option></select> <select id="to"><option value="">To city</option></select>

An element can only exist in one place. You need to make a clone of it
const listFrom = document.querySelector('#from');
const listTo = document.querySelector('#to');
listCities = ["a","b","c","d"];
listCities.forEach(function(city){
let option = document.createElement('option');
option.textContent = city;
option.value = city;
listFrom.appendChild(option);
listTo.appendChild(option.cloneNode(true));
});
<label for="from">From:</label><select id="from"></select>
<label for="to">To:</label><select id="to"></select>

Related

Viewbag Dropdown list from javascript always undefined

I try to make dynamically multiple input with dropdown list,
My select list is using viewbag and the result is always undefined.
The Viewbag List
private void ToolCategories(object selectedcat = null)
{
var catQuery = from d in db.Toolcategories
where d.In == "AD"
orderby d.CategoryName
select d;
SelectList ToolCategories = new SelectList(catQuery, "CategoryId", "CategoryName", selectedcat);
ViewBag.ToolCategories = ToolCategories;
}
The View
#using System.Text.Json;
<script>
var resin = document.createElement("div");
resin.setAttribute("class", "col-md-4");
var resinGrup = document.createElement("div");
resinGrup.setAttribute("class", "form-grup");
var resinLabel = document.createElement("label");
resinLabel.setAttribute("class", "form-label fs-6");
resinLabel.innerHTML = "Tool";
var jsonObj = #Html.Raw(JsonSerializer.Serialize(ViewBag.ToolCategories));
var resinSelect = document.createElement("select");
resinSelect.setAttribute("id", "CategoryId");
resinSelect.setAttribute("class", "form-control");
resinSelect.setAttribute("required", "");
resinSelect.setAttribute("name", `[${toolID}].ToolCategories`);
$.each(jsonObj, function (index, ToolCategories) {
var option = document.createElement("option");
option.value = ToolCategories.CategoryId;
option.text = ToolCategories.CategoryName;
resinSelect.append(option);
})
</script>
My select list is using viewbag and the result is always undefined.
Well, your undefined dropdown is pretty obvious because you have used SelectList which keeps data as Text and Value pairs. Thus, you are binding it within your $.each loop as CategoryId andCategoryName but the items is not residing there as it is. As you can see below:
Solution:
You need to modify your option binding as option.value = ToolCategories.Value; instead of ToolCategories.CategoryId;
Thereofore, complete code would be:
$.each(jsonObj, function (index, ToolCategories) {
console.log(ToolCategories);
var option = document.createElement("option");
option.value = ToolCategories.Value;
option.text = ToolCategories.Text;
resinSelect.append(option);
});
Output:
Note: If you still need further details on it, please have a look on our official document here.
Seems everything looks fine except below 2 lines, in your view file.. Replace your Category Id with Value and CategoryName with Text.
option.value = ToolCategories.Value;
option.text = ToolCategories.Text;
You are getting undefined as it failed to find values but required values mapped to different properties.

what is the right way to write this code?

im pretty sure the
tabelist.innerHTML = '<option>invalid value</option>'
isn't the best way to make an element and insert it in another one, but how i am supposed to do this if is not this way?
let submit = document.querySelector('input#submit')
let tabelist = document.querySelector('select#tabe')
submit.addEventListener('click', clicar)
function clicar(){
let tabenumber = 1
let number = Number(document.querySelector('input#number').value)
if(number == ''){
tabelist.innerHTML = '<option>invalid value</option>'
}else{
tabelist.innerHTML = ''
for(number*tabenumber; tabenumber <=10; tabenumber++){
tabelist.innerHTML += `<option>${number} x ${tabenumber} = ${number*tabenumber} </option>`
}
}
}
.innerHTML is valid, but should only be used as a last resort because it has potential side effects of:
wiping out event handlers that were set on elements that are now
being replaced
slowing down the rendering of the page because the HTML parser
must parse the new content
potentially exposing a security hole by allowing malicious script
to execute
Another approach would be to use the Document Object Model to create, configure and inject an element:
const list = document.querySelector("select");
// Create new element
const option = document.createElement("option");
// Configure new element
option.textContent = "Item 1";
// Inject into existing element
list.appendChild(option);
<select>
</select>

how to remove duplicates from Combobox in Javascript?

I fill a combobox via Javascript as follows:
let option = document.createElement("option");
option.innerHTML = elem.businessObject.get('id');
option.value = elem.businessObject.get('id');
taskTypeEl.appendChild(option);
whereby taskTypeE1 refers to the select - tag from my html-code
but unfortunately, I fill my combobox with a lot of duplicates. Is there an easy way
to get rid of that, such that every item only appears once?
Thanks in advance and kind regards
You can define a dictionary before starting the insertion of options, and only add the ones with the values that were not added before:
let dictionary = {}; //initiate
So when iterating to add the options, you can check if it is unique like this:
if(!dictionary[elem.businessObject.get('id')]){ //check for prev insertion
let option = document.createElement("option");
option.innerHTML = elem.businessObject.get('id');
option.value = elem.businessObject.get('id');
taskTypeEl.appendChild(option);
dictionary[elem.businessObject.get('id')] = option; //add option
}

populating select menu options using javascript

Suppose there is a select menu like this:"
<select id="dropDown"></select>
And I wish to populate it with an array value ["apple","mango","banana"];
How can this be achieved at one go without using any looping construct?
Here you can do like
var arr = ["apple", "mango", "banana"];
document.getElementById('dropdown').innerHTML =
'<option>' + arr.join('</option><option>') + '</option>';
JSFiddle
Without the use of a loop, you would do something like this:
var x = document.getElementById("dropDown");
var option = document.createElement("option");
option.innerHTML = "apple";
x.appendChild(option);
option = document.createElement("option");
option.innerHTML = "mango";
x.appendChild(option);
option = document.createElement("option");
option.innerHTML = "banana";
x.appendChild(option);
Obviously this assumes you know what the array values are going to be ahead of time. The most common way of doing this however would be to use a loop to iterate over the array.
If you just mean not using looping construct like for/while:
document.getElementById('dropDown').innerHTML = ["apple","mango","banana"].map(function(e) {
return "<option>"+e+"</option>";
}).join('');
The demo.
You'll want to do this:
var options = ["apple","mango","banana"],
select = document.getElementById('dropDown');
for(var i = 0; i < options.length; i++){
var option = document.createElement("option");
option.value = option.innerHTML = options[i];
select.appendChild(option);
}
The "No loops" requirement is really a bad idea. This is the most efficient way to build the list, in native JS. (Aside from micro optimizations in the loop)
It also doesn't use innerHTML on DOM elements that are rendered already, avoiding the need for the browser to re-structure the entire DOM.

use a javascript array to fill up a drop down select box

I have a text file which I am reading and storing the data in a javascript array, it's a list of cuisines. I want to use the array to fill up a drop down select box. I know how to hard code in the values for the drop down box (using correct me if i'm wrong) but I want to be able to use the array to fill it up instead.
<script type="text/javascript">
var cuisines = ["Chinese","Indian"];
</script>
<select id="CusineList"></select>
I have hard coded an array for simplicity, the "CuisineList" is my drop down box
Use a for loop to iterate through your array. For each string, create a new option element, assign the string as its innerHTML and value, and then append it to the select element.
var cuisines = ["Chinese","Indian"];
var sel = document.getElementById('CuisineList');
for(var i = 0; i < cuisines.length; i++) {
var opt = document.createElement('option');
opt.innerHTML = cuisines[i];
opt.value = cuisines[i];
sel.appendChild(opt);
}
DEMO
UPDATE: Using createDocumentFragment and forEach
If you have a very large list of elements that you want to append to a document, it can be non-performant to append each new element individually. The DocumentFragment acts as a light weight document object that can be used to collect elements. Once all your elements are ready, you can execute a single appendChild operation so that the DOM only updates once, instead of n times.
var cuisines = ["Chinese","Indian"];
var sel = document.getElementById('CuisineList');
var fragment = document.createDocumentFragment();
cuisines.forEach(function(cuisine, index) {
var opt = document.createElement('option');
opt.innerHTML = cuisine;
opt.value = cuisine;
fragment.appendChild(opt);
});
sel.appendChild(fragment);
DEMO
This is a part from a REST-Service I´ve written recently.
var select = $("#productSelect")
for (var prop in data) {
var option = document.createElement('option');
option.innerHTML = data[prop].ProduktName
option.value = data[prop].ProduktName;
select.append(option)
}
The reason why im posting this is because appendChild() wasn´t working in my case so I decided to put up another possibility that works aswell.

Categories