Creating a dynamic list using javascript - javascript

I have created a simple to do list which takes the value of the input and places it in a div and attaches some classes to them, everything works fine but how do I fix the for loop and make it work everytime and adds multiple divs under eachother instead of changing the existing one.
Here's my code:
let dynamicList = document.querySelector("#dynamic-list"),
dynamicDiv = document.createElement("div"),
dynamicClass = document.querySelector(".dynamic"),
circle = document.querySelector(".circle"),
paragraphTest = document.createElement("p"),
circleTest = document.createElement("div");
input.addEventListener("keypress", function(e){
value = input.value
if(e.key == "Enter"){
for(i=0; i<=dynamicList.children.length; i++){
dynamicList.insertBefore(dynamicDiv, dynamicClass.nextSibling)
let sibling = dynamicClass.nextSibling;
sibling.classList.add("dynamic")
sibling.appendChild(circleTest)
circleTest.classList.add("circle")
sibling.appendChild(paragraphTest)
paragraphTest.innerHTML = input.value
}
})
<div id="dynamic-list">
<div class="dynamic"><div class="circle"></div><p class="paragraph">some dummy text/p></div>
</div>
Here's what I mean:
https://imgur.com/a/Zgm48ze
That's what happens when I add text, it works perfectly. But when I add another text it overrides the first one instead of adding another div.

You should use createElement method every time you want to create that element. by just using it once, it will create only one, so if you change its property, you are editing the first element (the only one that has been created already).
so the code should be written like this :
let dynamicList = document.querySelector("#dynamic-list"),
dynamicClass = document.querySelector(".dynamic"),
circle = document.querySelector(".circle");
input.addEventListener("keypress", function(e) {
value = input.value
if (e.key == "Enter") {
const paragraphTest = document.createElement("p"),
dynamicDiv = document.createElement("div"),
circleTest = document.createElement("div");
for (i = 0; i <= dynamicList.children.length; i++) {
dynamicList.insertBefore(dynamicDiv, dynamicClass.nextSibling)
let sibling = dynamicClass.nextSibling;
sibling.classList.add("dynamic")
sibling.appendChild(circleTest)
circleTest.classList.add("circle")
sibling.appendChild(paragraphTest)
paragraphTest.innerHTML = input.value
}
}
})

Related

The value of input is not being assigned to a div

I want to get the text from the text area (id= getText), and than assign its value to the new div that I have created but the value is not being saved inside that new div.. I have tried many times but the value of the input is not saved and there is not change in when I click the button
let getText = document.getElementById("getText"); // this is textarea
let select = document.getElementById("selectBtn"); //this is button
//this is another div
let result = document.getElementById("result");
let new_p = document.createElement("div"); //creating element
new_p.innerHTML = "";
result.appendChild(new_p); // adding into resut div
//getting inner text of the input
let value = new_p.innerText;
//adding an event listener
select.addEventListener("click", function(e) {
e.preventDefault();
new_p.innerHTML = value;
//it does not works and the value is not saved
})
let getText = document.getElementById("getText"); // this is textarea
let select = document.getElementById("selectBtn"); //this is button
//this is another div
let result = document.getElementById("result");
let new_p = document.createElement("div"); //creating element
new_p.innerHTML = getText.value;
result.appendChild(new_p); // adding into resut div
//getting inner text of the input
let value = new_p.innerText;
//adding an event listener
select.addEventListener("click", function(e) {
e.preventDefault();
new_p.innerHTML = getText.value;
console.log(value)
//it does not works and the value is not saved
})
Replace new_p.innerHTML = ""; for
new_p.innerHTML = getText.value
and inside of click event,
new_p.innerHTML = getText.value;
Moving forward, try to use online code editors,
to post your code, Since it might be easier for anyone to assist you, Be aware to remove any personal info from the code.
Here is a fiddle with your code https://jsfiddle.net/k8b24n3q/12/
The reason was not working, was because you were setting on click event an undefined value.

Why does deleting this element with a non-unique ID delete the one I want?

Pardon the bad title, it's hard to explain. If you know how to phrase it better, please comment and I will update as soon as I can.
So, I was messing around with a random generator site (perchance.org) and writing my own HTML/Javascript to make my generator work. It has a behavior that is what I want, but that shouldn't be happening according to my knowledge of HTML.
Let me explain with a minimal example.
The example code here is to produce a simple page that has a button.
This button should generate <input>s with <button>s next to them, attached with similar ID's.
The button, when clicked, deletes the <input> and <button>.
Here is a snippet to show you the code/let you reproduce the results:
<html>
<head>
<script>
var current_id = 0;
function add_input () {
var list = document.getElementById("list");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
input.id = "input_" + current_id;
delete_button.id = "button_" + current_id;
br.id = "br_" + current_id;
input.value = input.id;
delete_button.textContent = "Delete";
delete_button.onclick = function () {
delete_input(this.id.slice(7)) //To get the numerical ID
}
list.appendChild(input);
list.appendChild(delete_button);
list.appendChild(br);
current_id++;
}
function delete_input (id) {
var input = document.getElementById("input_"+id);
var button = document.getElementById("button_"+id);
var br = document.getElementById("br_"+id);
input.remove();
button.remove();
br.remove();
current_id--;
}
</script>
</head>
<body>
<div id="list">
</div>
<button onclick="add_input()">Add</button>
</body>
</html>
When you add two inputs, then delete the first, and add one more, it leaves you with two inputs using the same ID. It also leaves you with two buttons with the same ID. And yet, both buttons delete their intended target.
Why?
You really should delegate - here I wrap in a div that can be removed in one go
You can rename each input to have incremented IDs but just letting the cnt run, gives you unique IDs
let cnt = 0;
function add_input() {
var list = document.getElementById("list");
var div = document.createElement("div");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
input.id = "input_" + (cnt++)// list.querySelectorAll("div").length
input.value = input.id;
delete_button.textContent = "Delete";
delete_button.classList.add("delete")
div.appendChild(input);
div.appendChild(delete_button);
div.appendChild(br);
list.appendChild(div);
}
window.addEventListener("load", function() {
document.getElementById("list").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("delete")) tgt.closest("div").remove();
})
})
<div id="list">
</div>
<button onclick="add_input()">Add</button>
I changed your code to be more effective.
I'm not using IDs as they aren't adding any benefit instead making it more complex.
Instead I target the element via the event handler and an argument.
I also wrap each set of inputs/buttons in a div so I can just remove that div and it will remove all of the children.
function add_input() {
var list = document.getElementById("list");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
delete_button.textContent = "Delete";
delete_button.onclick = function(e) {
e.target.parentNode.remove();
}
var div = document.createElement("div");
div.appendChild(input);
div.appendChild(delete_button);
div.appendChild(br);
list.appendChild(div)
}
<div id="list">
</div>
<button onclick="add_input()">Add</button>

Using something like getElementById for multiple objects?

Im currently using the document.getElementById("ID") method to fetch a value from an input area and paste it on a div.
This is working fine, but I would like paste these results in two different divs, meaning that I can't use the getElementById method.
I tried using getElementsByName but for some reason is not working.
Here's my JSFiddle with the working code using GetById. What I would like is to get it to output the elements in both Output areas and not just the first one.
var counter1 = 0; //Prevents user from creating multiple nodes on submit
var limit1 = 8; //Amount of nodes that can be created per input field
document.getElementById('textInput1').addEventListener('keypress', function (e) {
if (e.which === 13) {
e.stopPropagation();
e.preventDefault();
createNode1();
}
});
//CREATES FORMATTED NODE FROM INPUT VALUE
function createNode1(){
if (counter1 == limit1) {
//Do nothing
}
else {
var input = document.getElementById('textInput1').value; //Retrieves input
var newText = document.createElement("li"); //Creates the HTML node
newText.innerHTML = input; //Sets the node's value to whatever is in the input
document.getElementById("Form1").appendChild(newText); //Adds the node to the div
document.getElementById('textInput1').value=""; //Clears text field after submit
counter1++;
}
}
//CLEARS THE FORM IF YOU MADE A MISTAKE
function deleteNode1(){
var node = document.getElementById('Form1');
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
counter1=0;
}
}
USING IDs:
Try this ... using two calls ...
Output1:
<div id="Form1"></div>
<p>
Output2:
<div id="Form2"></div>
... and ...
var newText1 = document.createElement("li"); //Creates the HTML node
var newText2 = document.createElement("li"); //Creates the HTML node
newText1.innerHTML = input; //Sets the node's value to whatever is in the input
document.getElementById("Form1").appendChild(newText1); //Adds the node to the div
newText2.innerHTML = input; //Sets the node's value to whatever is in the input
document.getElementById("Form2").appendChild(newText2); //Adds the node to the div
Basically, I've created two li elements with the value. Then posted those to id's Form1 and Form2
USING CLASSes:
If you had used classes, you could loop through the getElementsByClassNamees.
Try ...
Output1:
<div id="Form1" class='formtype'></div>
<p>
Output2:
<div id="Form2" class='formtype'></div>
var classlist = document.getElementsByClassName("formtype");
for (var i=0; i<classlist.length; i++) {
var newText = document.createElement("li"); //Creates the HTML node
newText.innerHTML = input; //Sets the node's value to whatever is in the input
classlist[i].appendChild(newText); //Adds the node to the div
}

Attaching eventListener to dynamic elements in Javascript

I'm making a todo list and I have li and button tags added dynamically when adding a new list item. The button is an x which is supposed to remove the list item. I have tried several things but can't figure out how to make an eventListener for each individual x button and remove the corresponding list item when it is clicked.
The renderTodos function is where all of the dynamically added content is created. I have a data-index set to each button in which I was trying to use to access each button to attach an eventListener on each dynamic button, but I wasn't sure how to implement that. From what I have read there should be a way to do this using the currentTarget or target of the event but I don't understand how that works.
var input = document.querySelector('input[name=todoItem]'),
btnAdd = document.querySelector('button[name=add]'),
btnClear = document.querySelector('button[name=clear]'),
list = document.querySelector('.todo'),
storeList = [];
function renderTodos(){
var el = document.createElement('li'),
x = document.createElement('button');
listLength = storeList.length;
//Set text for remove button
x.innerHTML = 'x';
for(var i = 0; i < listLength; i++){
el.innerHTML = storeList[i];
list.appendChild(el);
x.setAttribute('data-index', i);
el.appendChild(x);
}
// check for correct data-index property on x button
}
function addTodos(){
storeList.push(input.value);
// Check that input is getting pushed to list array
console.log(storeList);
renderTodos();
}
function clearList(){
// make list empty
list.innerHTML = '';
storeList.splice(0, storeList.length);
//render empty list
renderTodos();
//Check that list array is empty
console.log(storeList);
}
btnAdd.addEventListener('click', addTodos);
btnClear.addEventListener('click', clearList);
Everything else on the list works so far I just can't figure out how to implement this eventListener.
One simple example can be
//a click hadler is added to #mylist which is already present in the dom
document.querySelector('#mylist').addEventListener('click', function(e) {
//assuming that the the `x` is in a span and it is the only span in the `li` we check for that, we can improve this check more to make sure we have actually clicked on the delete button
if (e.target.tagName == 'SPAN') {
//if so then since we know the structure we can delete the parent node of the target which is the span element
e.target.parentNode.parentNode.removeChild(e.target.parentNode);
}
}, false);
//kindly forgive the use of jQuery here
for (var i = 0; i < 10; i++) {
$('<li />', {
text: i
}).append('<span class="x">X</span>').appendTo('#mylist');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="mylist"></ul>
This is a very basic implementation of event delegation, where the actual event is bound to an ancestor element but then we use the actual event target to determine whether to act on it. We can improve the if condition to test for an class for any other attribute!!!
You can add a listener to each button using something like:
x.innerHTML = '';
x.onclick = function(){
var node = this.parentNode;
node.parentNode.removeChild(node);
};
Or you can keep the renderTodos code as it is and delegate the remove to the parent UL:
// Add the listener
list.addEventListener('click', removeItem);
// The listener function
function removeItem(event) {
var node = event.target;
// Check that the click came from an X button
// better to check against a class name though
if (node.tagName &&
node.tagName.toLowerCase() == 'button' &&
node.innerHTML == 'x') {
node = node.parentNode;
node.parentNode.removeChild(node);
}
}
basically what you want to do is add an event on the parent container and wait for the event to bubble up and identify if the event originating is from your x mark and if it is then trigger the callback function.. This is the concept I think most of the libraries use..
Or use a library like jQuery, why solve a problem that has already been solved by others.

javascript selected value

I have created function for creating a div, when u selet the value in dropdown box , based upon the length the number of divs will be created , so the code is
<select onchange="test()" id="selected_opt">
<option value="0" selected>-Select-</option>
<option value="1">Communication</option>
<option value="2">XXXXXXXXXXXXX</option>
</select>
the function test is
function test(){
var result = get_id.options[get_id.selectedIndex].value;
if(result == 1){
var i = 0,
c = model_details_json.communication,
j = c.length,
communications_div = document.getElementById("model_communication");
if(j == 0){
alert('nothing');
}
for (; i<j; i++){
var communication = c[i];
var create_div = document.createElement('div');
create_div.id = 'communication_id'+i;
create_div.name = 'communication';
var create_anchor = document.createElement('a');
create_anchor.innerHTML = communication.communication_name;
communications_div.appendChild(create_div);
document.getElementById(create_div.id).appendChild(create_anchor);
create_anchor.setAttribute("href", "javascript:void(0);");
create_anchor.setAttribute("onclick","sample('"+communication.communication_name+"','"+create_div.name+"')");
}
}
for example the length is 6 means the six number of divs will be created , so what the problem is when i again click on communication in select dropdown i.e already the six divs have been created , when do it again then agin six divs are created , so totally 12 divs created when u do it again it goes for 6 multiples.......
so what i need is the number of div would not be repeated. and it should be validate whether the user is clicking the same value in dropdown
Check this to remove div elements considering your parent div model_communication.
You need to implement logic by checking if the div exist and stop the loop when you get a message like 'Div is already removed' as shown in the example.
In order to do so create div elements along with id
var newdiv = document.createElement('div');
newdiv.setAttribute('id', id);
You need to remove all divs before create the new ones. Try adding a class name to it:
var create_div = document.createElement('div');
create_div.className = 'communication_div';
...
Now you can select the divs. Before the for statement add these lines to remove the divs with 'communication_div' class name:
var divs = document.getElementsByClassName('communication_div');
for(var i=0; i<divs.length; i++) {
divs[i].parentNode.removeChild(divs[i]);
}
Every script run will generate new divs and remove old ones.
use js map object to put selected value or length as key into the map then everytime user clicks a value, first check for its existence in the map. If not found in the map, that would mean length is not repeating and divs will be created.
something like:
var selectedValues = new Array();
.......
var result = get_id.options[get_id.selectedIndex].value;
if(selectedValues["val_"+result]) {
return;
}
selectedValues["val_"+result] = true;
you can check if the div is already created or present on page using getElementById('elementId') before creating it.
like in you code
for (; i<j; i++){
if(! document.getElementById('communication_id'+i)){ // do if element is not present on page
var communication = c[i];
var create_div = document.createElement('div');
create_div.id = 'communication_id'+i;
create_div.name = 'communication';
var create_anchor = document.createElement('a');
create_anchor.innerHTML = communication.communication_name;
communications_div.appendChild(create_div);
document.getElementById(create_div.id).appendChild(create_anchor);
create_anchor.setAttribute("href", "javascript:void(0);");
create_anchor.setAttribute("onclick",
"sample('"+communication.communication_name+"','"+create_div.name+"')");
}
}
Use replaceChild() instead of appendChild() on the Element object.

Categories

Resources