JS: Push to array and update select without getting duplicates - javascript

I am populating a SELECT with an array. The array contains strings with employee-names.
I want to be able to add a new employee name in the array and then update the SELECT. I've made this, but I keep getting duplicates as I call the function. I kind of understand why, but I haven't quite figured out yet how to make this code better so that I only add the one employee name that is written in the text input.
I don't want to have a function that removes all duplicates, as I think it should be possible to have several employees with the name "John".
My HTML:
<section id="sidebar">
<form onSubmit="return false">
<label for="Name">Name:</label>
<input id="nameInput" type="text" value="Your name here..." name="name" />
<input type="submit" value="Add to list" name="Add" onClick="addToArray();"><br>
<label for="Default">List over employees:</label>
<select id="employeeSelect">
</select>
</form>
</section>
My JS:
var employeeList = ['Sarah', 'Louse', 'Dan', 'John', 'Peter'];
function listEmployees(){
var select = document.getElementById('employeeSelect');
for (var i = 0; i < employeeList.length; i++)
{
var option = employeeList[i];
var newOption = document.createElement("option");
newOption.textContent = option;
newOption.value = option;
select.appendChild(newOption);
}
}
listEmployees();
function addToArray(){
var txtbox = document.getElementById('nameInput');
var value = txtbox.value;
employeeList.push(value);
listEmployees();
}

You're calling listEmployees() (which adds, and re-adds, everything in your list) each time a new name is added.
I'd move the add-a-new-option code out to its own function. Call it for each name in the original list, then call it again when a new name is added.
var employeeList = ['Sarah', 'Louse', 'Dan', 'John', 'Peter'];
function addEmployee(name) {
var select = document.getElementById('employeeSelect');
var newOption = document.createElement("option");
newOption.textContent = name;
newOption.value = name;
select.appendChild(newOption);
}
function listEmployees() {
for (var i = 0; i < employeeList.length; i++) {
addEmployee(employeeList[i])
}
}
listEmployees();
function addToArray() {
var txtbox = document.getElementById('nameInput');
var value = txtbox.value;
employeeList.push(value); // update the list
addEmployee(value); // update the select
}
<section id="sidebar">
<form onSubmit="return false">
<label for="Name">Name:</label>
<input id="nameInput" type="text" placeholder="Your name here..." name="name" />
<input type="submit" value="Add to list" name="Add" onClick="addToArray();">
<br>
<label for="Default">List over employees:</label>
<select id="employeeSelect">
</select>
</form>
</section>

Related

How to clone or create a nested DOM node and change all its containing id values according to a current id?

I need to display some numbers, strings from a class named Student, but i can't figure it out how i can change the id from children element. I have to use JavaScript.
what i tried to do:
class Student{
static count = 0;
constructor(nume, prenume, data_nasterii, foaie_matricola){
this.IdClasa = ++Student.count;
//definirea atributelor
this.nume = nume;
this.prenume = prenume;
this.data_nasterii = data_nasterii;
this.foaie_matricola = foaie_matricola;
}
afiseazaVarsta(){
}
afiseazaNotele(){
}
calculeazaMedia(){
}
adaugaNota(nota_noua){
}
}
var Stud = [new Student("Name", "Name1", "2000.01.01", "0123123"),
new Student("Green", "Blue", "2022/12.12", "321321")];
function afisareStudenti(){
let i = 0; let bol = false;
for(let x=1; x<=Student.count; x++) {
console.log(document.getElementById("AfisareStudenti"+x)==null);
if(document.getElementById("AfisareStudenti"+x)==null)
{
i = x;
bol = true;
break;
} else {
bol = false;
}
}
if((i<=Student.count)&&(bol==true)){
for(i; i<=Student.count; i++) {
console.log("i="+i);
var div = document.querySelector('#AfisareStudenti1');
var divClone = div.cloneNode(true);
console.log(divClone);
divClone.id = 'AfisareStudenti'+(i);
div.after(divClone);
var NumeStud = document.getElementById("NumeStudent"+(i-1));
var PrenumeStud = document.getElementById("PrenumeStudent"+(i-1));
var dataNastStud = document.getElementById("intData"+(i-1));
var FoaiaMatStud = document.getElementById("FoaiaMatStud"+(i-1));
NumeStud.id = "NumeStudent"+(i);
PrenumeStud.id = "PrenumeStud"+(i);
dataNastStud.id = "intData"+(i);
FoaiaMatStud.id = "FoaiaMatStud"+(i);
}
}
}
and this is the html file(the div that i want to clone):
<!--AFISARE-->
<div id="AfisareStudenti1">
<h2> Afisare Student 1</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent1"><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent1"><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData1"><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud1"><br><br>
<input class="butoane" type="submit" value="Afisare"
onclick="afisareMeniuAfisStudenti()">
</form>
</div>
the class is saved in a dynamic array (could be n object of the class) so i have to make somehow to display the information dynamic. My version changes the id from all elements with the same id (every incrementation of i, the idnumber from id is incremented also). I tried to create that div with document.createElement but is impossible(at least for me) xD . I started coding in javascript 2 days ago, so please take it slow on me :(
I think i found the problem, but it doesn't solve it. (i need to put (i-1) when calling for getting the ids). (Newbie mistake)
Having commented ...
"I have the feeling that if provided with the broader picture the audience could be of much more help since the OP could be provided back with leaner/cleaner and better maintainable approaches."
... I nevertheless hereby lately provide a template-based approach which, besides supporting the OP's id based querying of student-items, is also easier to read and to maintain.
The code provided within the example-code's main function does not just implement the usage of the template-based node-creation via template literals and DOMParser.parseFromString but also prevents the default behavior of each student-form's submit-button by making use of event-delegation.
function createStudentElement(studentId) {
const markup =
`<div class="student-item" id="AfisareStudenti${ studentId }">
<h2> Afisare Student ${ studentId }</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent${ studentId }"><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent${ studentId }"><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData${ studentId }"><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud${ studentId }"><br><br>
<input
class="butoane" type="submit" value="Afisare"
onclick="afisareMeniuAfisStudenti(${ studentId })"
>
</form>
</div>`;
const doc = (new DOMParser).parseFromString(markup, 'text/html');
return doc.body.removeChild(doc.body.firstElementChild);
}
// the button click handler.
function afisareMeniuAfisStudenti(studentId) {
console.log({ studentId })
}
function main() {
const itemsRoot = document.querySelector('.student-items');
// - prevent any form-submit by making use of event-delegation.
itemsRoot.addEventListener('submit', evt => evt.preventDefault());
// - just for demonstration purpose ...
// ... create student-items from a list of student IDs.
[1, 2, 3, 4, 5].forEach(studentId =>
itemsRoot.appendChild(
createStudentElement(studentId)
)
);
}
main();
.as-console-wrapper { left: auto!important; width: 50%; min-height: 100%; }
<div class="student-items"></div>
Tom's answer above is what you want for the element id problem that you asked about.
For your code in particular, you are going to have a couple other problems:
Because the final input is type="submit", its going to reload the page by default when it is clicked. The name of the "onclick" function also needs to match the function you defined (afisareStudenti).
You have:
<input class="butoane" type="submit" value="Afisare" onclick="afisareMeniuAfisStudenti()">
Change this to:
<input class="butoane" type="submit" value="Afisare" onclick="afisareStudenti(event)">
Now, when you click that button, it will call the afisareStudenti function and pass in the "event". So if you change:
function afisareStudenti(){
let i = 0; let bol = false;
to:
function afisareStudenti(event){
event.preventDefault()
let i = 0; let bol = false;
This will correctly call your function, and prevent the "default" action of that submit button from reloading the page.
To change the id attribute of children elements, you could use Element.querySelector() on divClone.
Because if you use Document.querySelector() or Document.getElementById() you will get the first element that matches your selector (i.e.children of div#AfisareStudenti1).
let i = 2;
var div = document.querySelector('#AfisareStudenti1');
var divClone = div.cloneNode(true);
divClone.id = 'AfisareStudenti'+(i);
divClone.querySelector("h2").innerText = "Afisare Student " + i;
var NumeStud = divClone.querySelector("#NumeStudent1");
var PrenumeStud = divClone.querySelector("#PrenumeStudent1");
var dataNastStud = divClone.querySelector("#intData1");
var FoaiaMatStud = divClone.querySelector("#FoaiaMatStud1");
NumeStud.id = "NumeStudent"+(i);
PrenumeStud.id = "PrenumeStud"+(i);
dataNastStud.id = "intData"+(i);
FoaiaMatStud.id = "FoaiaMatStud"+(i);
div.after(divClone);
<div id="AfisareStudenti1">
<h2> Afisare Student 1</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent1" /><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent1" /><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData1" /><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud1" /><br><br>
<input class="butoane" type="submit" value="Afisare" onclick="afisareMeniuAfisStudenti()" />
</form>
</div>

How to place values from html inputs into a javascript array of objects

I have three inputs which will be given by the user and i want these 3 inputs to make up objects in an array in my javascript file, i.e, the values for these 3 inputs will make up each object in thearray, everytime the user inputs the 3 values and clicks enter, a new object with those 3 values as properties should be added into the array. How do i achieve this?
I have tried to get the values, and onclick to push them into the array but i keep get a "Cannot access 'arr_items' before initialization
at addName"
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
const arr_items = [];
let i = 0;
function addValues() {
arr_items[i].name.push(input2.value);
arr_items[i].weight.push(input3.value);
arr_items[i].value.push(input4.value);
i++;
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" placeholder="enter item name">
<button onclick="addValues()" id="name">Enter</button>
<input id="itemWeight" type="number" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" placeholder="enter item value">
</div>
I expect everytime the user inputs the 3 values and clicks enter, a new object with those 3 values as properties should be added into the array.
You are trying to call the property name, weight etc on the array element using .. This is wrong. Try do:
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
const arr_items = [];
let i = 0;
function addValues() {
arr_items[i] = {
name: input2.value,
weight: input3.value,
value: input4.value
};
i++;
console.log(arr_items)
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" placeholder="enter item name">
<button onclick="addValues()" id="name">Enter</button>
<input id="itemWeight" type="number" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" placeholder="enter item value">
</div>
You were doing it wrongly try this:
const arrayItems = new Array();
function addValues(){
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
let inputs = {
input1 : input2.value,
input3 : input3.value,
input4 : input4.value
}
arrayItems.push(inputs);
console.log(arrayItems);
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" placeholder="enter item name">
<input id="itemWeight" type="number" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" placeholder="enter item value">
<button onclick="addValues()" id="name">Enter</button>
</div>
You can just push to array again and again without counter. Like so:
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
const arr_items = [];
function addValues() {
arr_items.push({name: input2.value, weight: input3.value, value: input4.value});
console.log(arr_items);
}
Here is a small chunk of code, that I stripped down, that takes every input field, within a parent, that has a name attribute and uses those name attribute values as the keys in an object.
If uses the value of the input fields as the values in the object.
This allows the output object to change based on which input fields are in the parent element. If the input element does not have a name then it is not included.
This code can be reused and it always hands back the object needed.
const getEls = srcEl => {
const subs = [...srcEl.querySelectorAll('[name]')];
return subs.reduce((acc, sub) => {
acc[sub.getAttribute('name')] = sub.value;
sub.value = '';
return acc;
}, {});
subs[0].focus();
}
let results = [];
function doIt() {
const srcEl = document.getElementById('container');
const values = getEls(srcEl);
results.push(values);
console.log(JSON.stringify(values,0,20));
}
const btn = document.getElementById('submit');
btn.addEventListener('click', doIt);
const resultsBtn = document.getElementById('show');
resultsBtn.addEventListener('click', () => {
console.log(JSON.stringify(results,0,2));
});
<div id="container">
<p>Items Information:</p>
<input id="itemName" name="name" type="text" placeholder="enter item name"/><br/>
<input id="itemWeight" name="weight" type="number" placeholder="enter item weight(kg)"/><br/>
<input id="itemValue" name="value" type="number" placeholder="enter item value"/><br/>
<button id="submit">Enter</button>
<hr/>
<button id="show">Results</button>
</div>
There are two main aspects to note in the answer. One is that the array should be declared as a variable (not a constant), the other is that you should move the input var code into the function.
I added an alert so that you can see the outcome (wasn't sure if you wanted to allow them to be added without weight etc? This would cause confusion in your storage/retrieval of data.. so I moved the enter button)
Hope this helps
var arr_items = [];
function addValues() {
let input2 = document.getElementById("itemName");
let input3 = document.getElementById("itemWeight");
let input4 = document.getElementById("itemValue");
var item2 = input2.value + " " + input3.value + " " + input4.value;
arr_items.push(item2);
alert( [arr_items]);
}
<div>
<p>Items Information:</p>
<input id="itemName" type="text" name="item" placeholder="enter item name">
<input id="itemWeight" type="number" name="item" placeholder="enter item weight(kg)">
<input id="itemValue" type="number" name="item" placeholder="enter item value">
<button id="name" onclick="addValues()">Enter</button>
</div>

create input text with loop js

I would like to know how could I create many <input type=text /> tags with a loop in JS.
I need that loop to be linked to a first input (type=number), which tell to the loops how many input text to create.
function getP () {
var nbP = Number(document.getElementById("nombreP").value);
for (var i = 0; i < nbP; i++) {
var newForm = document.createElement("input[type=text]");
newForm.id = "form"+i
document.body.appendChild(newForm);
}
}
<form method="get">
<input type="number" name="nombrePlat" id="nombreP">
<input type="submit" value="Envoyer" id="ok" onclick="getP()">
</form>
Direct answer to your question:
<script type="text/javascript">
function getP() {
var nbP = +document.getElementById("nombreP").value;
var inputContainer = document.getElementById("inutContainer");
for (var i = 0; i < nbP; i++) {
var newForm = document.createElement("input");
newForm.setAttribute("type", "text");
newForm.setAttribute("id", "form"+i);
inputContainer.appendChild(newForm);
inputContainer.appendChild(document.createElement("br"));
}
}
</script>
<form>
<input type="number" name="nombrePlat" id="nombreP">
<input type="button" value="Envoyer" id="ok" onclick="getP()">
<div id="inutContainer">
</div>
</form>
BUT: this is good question to learn about Javascript and HTML, but bad to create powerfull UI. To implement modern UI in JS/HTML i am strongly recommend to learn more abou next technologies:
https://reactjs.org/ or https://angular.io/ or https://vuejs.org/
I hope it helps:
document.querySelector('#ok').addEventListener('click', getP)
function getP(event) {
let inputsQtt = document.querySelector('input[type=number]').value
for (let i = 0; i < inputsQtt; i++) {
let input = document.createElement("input");
document.body.appendChild(input);
}
}
<form method="get">
<input type="number" name="nombrePlat" id="nombreP">
<input type="button" value="Envoyer" id="ok">
</form>
There are few problems with your code
First: syntax error, you are missing 1 curly bracket } to close function.
And second and more important as you click on button it causes to submit form and refreshes the page.To solve this you just need to change type of button from submit to button.
And also you can not use "input[type=text]" to create element.You can just create an element with following code
function getP () {
var nbP = Number(document.getElementById("nombreP").value);
for (var i = 0; i < nbP; i++) {
var newForm = document.createElement("input");
newForm.id = "form"+i;
newForm.setAttribute("type","text");
document.body.appendChild(newForm);
}
}
Here's a slightly different approach, that involves adding a wrapper container within your form.
function updateForm() {
var parent = document.getElementById('inputs'),
count = document.getElementById('inputCount').value || 0;
parent.innerHTML = '';
for (let i = 0; i < count; i++) {
parent.innerHTML += `<input placeholder="text input ${i+1}" name="form${i+1}" id="form${i+1}" /><br>`;
}
}
<form method="get" name="inputForm">
<input min="0" type="number" name="inputCount" id="inputCount">
<div id="inputs">
<!-- container for dynamic inputs -->
</div>
</form>
<!-- Notice inputs can also be associated to form with `form` attribute -->
<input form="inputForm" type="submit" value="Make" id="ok" onclick="updateForm()">

Simplifying code using localStorage

I wanted to find out whether it was possible to use a loop to simplify all this rather than hard-coding the entire structure. For the second part of my Javascript where I tried to store the user inputs into localStorage using a for loop, I'm getting an error where it says
CreateEvent.js:72 Uncaught TypeError: name.push is not a function at createReplace (CreateEvent.js:72) at HTMLButtonElement.onclick (CreateEvent.html:130)
HTML:
<span class="border1">
<input class="forms" type="text" id="title" placeholder="Enter Title!">
<p id="title1"></p>
<input class="forms" type="text" id="brief" placeholder="Enter brief description!">
<p id="brief1"></p>
</span>
<div class="Hovertrees">
<p>Hover over me!</p>
<span class="Hovertrees2">
<input class="hover" type="text" id="hover" placeholder="Enter some fun facts!">
<p id="hover1"></p>
</span>
</div>
<div id="what">
<input class="forms" type="text" id="whattitle" placeholder="What is this event?">
<h2 id="whattitle1"></h2>
<input class="forms" type="text" id="whatdesc" placeholder="Enter brief description!">
<p id="whatdesc1"></p>
</div>
<div id="why">
<input class="forms" type="text" id="whytitle" placeholder="Why is this event important?">
<h2 id="whytitle1"></h2>
<input class="forms" type="text" id="whydesc" placeholder="Description of this event">
<p id="whydesc1"></p>
</div>
<div id="fun">
<input class="forms" type="text" id="funtitle" placeholder="Anything interesting you can add!">
<h3 id="funtitle1"></h3>
<input class="forms" type="text" id="fundesc" placeholder="Description of the interesting info!">
<p id="fundesc1"></p>
</div>
Javascript:
var title;
var brief;
var hover;
var whatTitle;
var whatDesc;
var whyTitle;
var whyDesc;
var funTitle;
var funDesc;
function createReplace() {
title = document.getElementById('title').value;
document.getElementById('title1').innerHTML = title;
document.getElementById('title').className = 'hidden';
document.getElementById('news').innerHTML = title;
brief = document.getElementById('brief').value;
document.getElementById('brief1').innerHTML = brief;
document.getElementById('brief').className = 'hidden';
hover = document.getElementById('hover').value;
document.getElementById('hover1').innerHTML = hover;
document.getElementById('hover').className = 'hidden';
whatTitle = document.getElementById('whattitle').value;
document.getElementById('whattitle1').innerHTML = whatTitle;
document.getElementById('whattitle').className = 'hidden';
whatDesc = document.getElementById('whatdesc').value;
document.getElementById('whatdesc1').innerHTML = whatDesc;
document.getElementById('whatdesc').className = 'hidden';
whyTitle = document.getElementById('whytitle').value;
document.getElementById('whytitle1').innerHTML = whyTitle;
document.getElementById('whytitle').className = 'hidden';
whyDesc = document.getElementById('whydesc').value;
document.getElementById('whydesc1').innerHTML = whyDesc;
document.getElementById('whydesc').className = 'hidden';
funTitle = document.getElementById('funtitle').value;
document.getElementById('funtitle1').innerHTML = funTitle;
document.getElementById('funtitle').className = 'hidden';
funDesc = document.getElementById('fundesc').value;
document.getElementById('fundesc1').innerHTML = funDesc;
document.getElementById('fundesc').className = 'hidden';
document.getElementById("create").className = "hidden";
var varNames = [
'titles',
'brief',
'hover',
'whatTitle',
'whatDesc',
'whyTitle',
'funtitle',
'fundesc'
]
for (var name in varNames) {
var value = window[name]
var obj = {name : value};
if(localStorage.getItem(name) != null) {
var tmp = JSON.parse(localStorage.getItem(name));
for(var i = 0;i<tmp.length;i++) {
name.push(tmp[i]);
}
}
name.push(obj);
localStorage.setItem(name, JSON.stringify(value));
}
}
For the first part, simplifying is not possible since you have different properties for each elements.
For the second part, you are getting error because push is a method for array object.But name is an string object declared in for loop
for (var name in varNames) {
var value = window[name]
var obj = {name : value};
if(localStorage.getItem(name) != null) {
var tmp = JSON.parse(localStorage.getItem(name));
for(var i = 0;i<tmp.length;i++) {
name.push(tmp[i]);
}
}
name.push(obj);
localStorage.setItem(name, JSON.stringify(value));
}
}
You can set item in loop
localStorage.setItem(1,'name1');
localStorage.setItem(2,'name2');
localStorage.setItem(3,'name2');
1 2 and 3 would be key that you want to set and then get according to these keys.
localStorage.key(index)
By passing index in key method it will return you the value of that key.

How to display array from local storage in html element?

Obviously, a beginner's question:
How do I get array data to display in an html element using html and javascript?
I'd like to display the user saved array data in a paragraph tag, list tag, or table tag, etc.
[http://www.mysamplecode.com/2012/04/html5-local-storage-session-tutorial.html]
Above is a link to the kindly provided example of localStorage except how to display the array on the html page rather than in the console.log.
Below is the code snip that demonstrates what I'm trying to do.
function saveArrayData() {
console.log("Saving array data to local storage.");
var myArrayObject = [];
var personObject1 = new Object();
personObject1.name = "Array1";
personObject1.age = 23;
myArrayObject.push(personObject1);
var personObject2 = new Object();
personObject2.name = "Array2";
personObject2.age = 24;
myArrayObject.push(personObject2);
var personObject3 = new Object();
personObject3.name = "Array3";
personObject3.age = 25;
myArrayObject.push(personObject3);
localStorage.setItem("persons", JSON.stringify(myArrayObject));
}
function restoreArrayData() {
console.log("Restoring array data from local storage.");
var myArrayObject = JSON.parse(localStorage.getItem("persons"));
for (var i = 0; i < myArrayObject.length; i++) {
var personObject = myArrayObject[i];
console.log("Name: " + personObject.name, "Age: " + personObject.age);
}
}
<label for="name">Name:</label>
<input type="text" data-clear-btn="true" name="name" id="name" value="">
<label for="age">Age:</label>
<input type="text" data-clear-btn="true" name="age" id="age" value="">
<br>
<br>
<input type="button" id="sArray" value="Save Array data" onclick="Javascript:saveArrayData()">
<input type="button" id="rArray" value="Restore Array data" onclick="Javascript:restoreArrayData()">
<p id="displayArrayDataHere"></p>
You should update your code like below:
function restoreArrayData() {
var myArrayObject = JSON.parse(localStorage.getItem("persons"));
$("#displayArrayDataHere").append("<table>");
myArrayObject.forEach(function(personObject) {
$("#displayArrayDataHere").append("<tr><td>"+personObject.name+"</td><td>"+personObject.age+"</td></tr>")
})
$("#displayArrayDataHere").append("</table>");
}

Categories