after months of doing courses, I finally ventured into coding my first project, but the most basic functionality of it isn't working.
I'm doing a simple to do list, and im working on it actually displaying the elements added by the user through the button but they don't appear on the screen after clicking, even if i'm using DOM manipulation commands to create an 'ul' element. Also, the page refreshes after every click on the button.
let addToButton = document.getElementById('addButton');
let inputFieldset = document.getElementById('toDoInput');
let toDoContainer = document.getElementById('toDoList');
addToButton.addEventListener('click', function(){
let toDoStuff = document.createElement('ul')
toDoStuff = inputFieldset.value
toDoContainer.append(toDoStuff);
})
<!DOCTYPE html>
<html lang="en">
<head>
<title>la lista</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="list-style.css"/>
</head>
<body>
<main>
<h1>Ysmael's To-Do List</h1>
<h3>Input your activities</h3>
<form>
Input something<input type="text" required id="toDoInput" placeholder="Input your stuff"/><button id="addButton" type="submit">+</button>
</form>
<div id="toDoList">
</div>
</main>
<script href="todolist.js"></script>
</body>
</html>
Acording to my logic, it should work, but I'm clearly doing one or more things wrong.
to not submit the form, replace the <button> with <input type="button" value="+"> and to create list you want <li> element with the parent <ul>
let addToButton = document.getElementById('addButton');
let inputFieldset = document.getElementById('toDoInput');
let toDoContainer = document.getElementById('toDoList');
addToButton.addEventListener('click', function() {
// show warning if input empty
if (!inputFieldset.reportValidity()) // or use: if (!inputFieldset.value)
return
let toDoStuff = document.createElement('li')
toDoStuff.innerHTML = inputFieldset.value
toDoContainer.append(toDoStuff);
// reset input
inputFieldset.value = '';
})
<h3>Input your activities</h3>
<form>
Input something <input type="text" required id="toDoInput" placeholder="Input your stuff" />
<button id="addButton">+</button>
</form>
<ul id="toDoList">
</ul>
For problem #1:
In line 6 you are creating the let binding toDoStuff which holds a <ul>-element, just to override toDoStuff in line 7 with the current value of the <input>-element. Even if it worked (somehow), I suspect it wouldn't work as you expect, because it would create a completely new list for each todo instead of creating a single list of todos. If I'm right, move the let toDoStuff = document.createElement('ul') line out of your event handler function, create the <ul> right away and .append() it to your toDoContainer (hold a reference to it so that you can append elements to it later).
let toDoContainer = document.getElementById('toDoList');
let toDoStuff = document.createElement('ul');
toDoContainer.append(toDoStuff);
Then, inside the click handler function, create an <li> element that you can append to the <ul>:
addToButton.addEventListener('click', function () {
let toDoListItem = document.createElement('li');
// ... elided
});
The .append() method of an HTMLElement expects to receive another HTMLElement or Node, but you are passing it a String. This means you need to transform that String into a Node before passing it to .append(), and the usual way to do that transformation is via document.createTextNode().
let toDoText = document.createTextNode(inputFieldset.value)
However, you want to insert that Node into a <ul> element and the only child elements of an unordered list should be <li>-elements. This is why we generated the <li> in the previous sections, so all you have to do now is adding the Node to the <li>, then adding the <li> to the <ul>. In code:
addToButton.addEventListener('click', function () {
let toDoListItem = document.createElement('li');
let toDoText = document.createTextNode(inputFieldset.value);
toDoListItem.append(toDoText);
toDoStuff.append(toDoListItem);
});
In regards to the #2 submission problem:
Your button is nested inside a <form> element, so pressing it "naturally" submits the form. What you want to do is to suppress the submission, either via:
calling .preventDefault() on the generated SubmitEvent object of the form
returning false in your event handler function
In favor of a standards way, use .preventDefault(), so we need a reference to the <form> element instead of the <button> as well as changing the event type from 'click' to 'submit':
// ... elided
let addToButton = document.querySelector('form');
// ... elided
addToButton.addEventListener('submit', function (event) { // <-- changed click to submit, added generated event object
event.preventDefault(); // <-- suppress form submission
let toDoListItem = document.createElement('li');
// ... elided, see above
});
Changing the variable names to appropriate ones is left as an excercise ;-)
Example:
let addToButton = document.querySelector('form');
let inputFieldset = document.getElementById('toDoInput');
let toDoContainer = document.getElementById('toDoList');
let toDoStuff = document.createElement('ul');
toDoContainer.append(toDoStuff);
addToButton.addEventListener('submit', function (event) {
event.preventDefault();
let toDoListItem = document.createElement('li');
let toDoText = document.createTextNode(inputFieldset.value);
toDoListItem.append(toDoText);
toDoStuff.append(toDoListItem);
})
<!DOCTYPE html>
<html lang="en">
<head>
<title>la lista</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="list-style.css"/>
</head>
<body>
<main>
<h1>Ysmael's To-Do List</h1>
<h3>Input your activities</h3>
<form>
Input something<input type="text" required id="toDoInput" placeholder="Input your stuff"/><button id="addButton" type="submit">+</button>
</form>
<div id="toDoList">
</div>
</main>
<script href="todolist.js"></script>
</body>
</html>
One of the solutions to prevent reloading the page after submitting the form is to use even.preventDefault() on submit event. In this way you prevent default browser's behavior. Anyway, to do so, you should add submit event listener. You can also add submitted task to the list from there, therefore I replaced your 'click' event handler with submit.
<script> tag shouldn't have href attribute. It should be src instead.
You are creating <ul> element which is a container for the list of unordered elements. You should create <li> element and append it to <ul> or <ol> container. I have replaced tasks container from <div> to <ul>.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>la lista</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="list-style.css" />
</head>
<body>
<main>
<h1>Ysmael's To-Do List</h1>
<h3>Input your activities</h3>
<form id="toDoForm">
Input something
<input type="text" required id="toDoInput" placeholder="Input your stuff" />
<button id="addButton" type="submit">+</button>
</form>
<ul id="toDoList">
</ul>
</main>
<script src="todolist.js"></script>
</body>
</html>
tasklist.js:
let inputFieldset = document.getElementById('toDoInput');
let toDoContainer = document.getElementById('toDoList');
let toDoForm = document.getElementById('toDoForm');
toDoForm.addEventListener('submit', (event) => {
event.preventDefault();
const task = document.createElement('li');
task.innerText = inputFieldset.value;
toDoContainer.appendChild(task);
inputFieldset.value = '';
})
Change button type to button instead of submit to keep everything from disappearing when it's clicked, and change toDoList element from div to ul and then add tasks as li [list items] rather than ul [a whole unordered list in itself]. Also, you need to change the innerHTML (or innerText) of toDoStuff instead of setting the element itself (so that it remains a li).
let addToButton = document.getElementById('addButton');
let inputFieldset = document.getElementById('toDoInput');
let toDoContainer = document.getElementById('toDoList');
addToButton.addEventListener('click', function(){
let toDoStuff = document.createElement('li');
toDoStuff.innerHTML = inputFieldset.value;
toDoContainer.append(toDoStuff);
inputFieldset.value = "";//clear field
})
//so that "enter" does the same as addToButton instead of submit
inputFieldset.addEventListener("keydown", function(event) {
if (event.key === "Enter") {
event.preventDefault();
addToButton.click();
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>la lista</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="list-style.css"/>
</head>
<body>
<main>
<h1>Ysmael's To-Do List</h1>
<h3>Input your activities</h3>
<form>
Input something<input type="text" required id="toDoInput" placeholder="Input your stuff"/><button id="addButton" type="button">+</button>
</form>
<ul id="toDoList">
</ul>
</main>
<script href="todolist.js"></script>
</body>
</html>
I've also added a line to clear the field [for the next task] after a task has been added, and another event listener to the text input because "enter" key can also register as submit - but now, instead of everything disappearing on enter, it simulates clicking the add button.
I changed your code. The problems are 3 in number.
you have button type submit, this submits the form and the form then requires an action to handle the submit, this is typically used to send data to other pages.(dont quote me on that, i never use it)
you made toDoStuff get the value of the input thus overriding the create element.
you had a div as a container for a created ul when you want to have a ul as container for a created li.
Here is the changed html:
<body>
<main>
<h1>Ysmael's To-Do List</h1>
<h3>Input your activities</h3>
<form>
Input something<input type="text" required id="toDoInput" placeholder="Input your stuff"/><button id="addButton" type="button">+</button>
</form>
<ul id="toDoList">
</ul>
</main>
</body>
And here is the changed Javascript:
let addToButton = document.getElementById('addButton')
let inputFieldset = document.getElementById('toDoInput')
let toDoContainer = document.getElementById('toDoList')
addToButton.addEventListener('click', () => {
let toDoStuff = document.createElement('li')
toDoStuff.innerHTML = inputFieldset.value
toDoContainer.append(toDoStuff)
})
Good luck and happy coding, dont let a setback make you give up!
Bind the <form> to the "submit" event. Details are commented in example.
// Reference <form>
const todo = document.forms.todo;
// Reference <input>
const add = todo.elements.add;
// Reference <ul>
const list = document.querySelector(".list");
/**
* Bind <form> to "submit" event
* Stop <form> from sending data and blanking out the page
* Create <li> which is required in a <ul>
* Add the value of <input> as the text of <li>
* Add <li> to <ul>
* Clear the <form> to prevent accidental clicking
*/
todo.addEventListener('submit', function(event) {
event.preventDefault();
const item = document.createElement('li')
item.textContent = add.value
list.append(item);
this.reset();
});
<main>
<!-- Add #id or [name] to <form> -->
<form id="todo">
<fieldset>
<legend>Ysmael's To-Do List</legend>
<!-- Add <label> and [for="{<input> #id}"] -->
<label for="add">Enter Task: </label>
<input id="add" type="text" required>
<!-- A plain <button> inside a <form> will trigger "submit" -->
<button>+</button>
</fieldset>
</form>
<ul class="list"></ul>
</main>
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>ToDo</title>
</head>
<body>
<h1>To Do List</h1>
<label>Enter What You Have To Do:</label>
<br>
<br>
<input type="text" id="toDo">
<br>
<br>
<button type="button" id="myButton">Submit</button>
<button type="button" id="clearList">Clear List</button>
<br>
<ul id="list"></ul>
<script src="todojs.js"></script>
</body>
</html>
JAVASCRIPT
document.getElementById('myButton').onclick = function () {
const doIt = document.getElementById('toDo').value;
const li = '<li id="item">' + doIt + '<button type="button" id="clearOne">X</button>' + '</li>';
document.getElementById('list').insertAdjacentHTML('beforeend', li);
document.getElementById('toDo').value = '';
document.getElementById('clearList').onclick = function() {
const ul = document.getElementById('list');
while (ul.hasChildNodes()) {
ul.removeChild(ul.firstChild);
}
}
document.getElementById('clearOne').onclick = function () {
const currentLi = document.getElementById('item');
currentLi.removeChild();
}
}
SO im putting a X next to each to do and i want to be able to remove the one LI element when the user presses the X but i keep failing i tried multiple things cants figure it out
I think this what you are looking for.
document.getElementById('myButton').onclick = function () {
const doIt = document.getElementById('toDo').value;
// create li element.
const li = document.createElement('li');
li.innerText = doIt;
// create remove button.
const removeButton = document.createElement('button');
// Set text of remove button
removeButton.innerText = 'X';
// Add event listener for the remove button.
removeButton.addEventListener('click', function() { this.parentNode.remove() } )
// append the button inside the li element
li.append(removeButton);
// prepend the li element in the list.
document.getElementById('list').prepend(li);
document.getElementById('toDo').value = '';
document.getElementById('clearList').onclick = function() {
const ul = document.getElementById('list');
ul.innerHTML = '';
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>ToDo</title>
</head>
<body>
<h1>To Do List</h1>
<label>Enter What You Have To Do:</label>
<br>
<br>
<input type="text" id="toDo">
<br>
<br>
<button type="button" id="myButton">Submit</button>
<button type="button" id="clearList">Clear List</button>
<br>
<ul id="list"></ul>
<script src="todojs.js"></script>
</body>
</html>
An easy way would be:
function remove(el) {
el.parentElement.remove();
}
document.getElementById('myButton').onclick = function () {
const doIt = document.getElementById('toDo').value;
const li = '<li id="item">' + doIt + '<button type="button" onClick="remove(this)" id="clearOne">X</button>' + '</li>';
document.getElementById('list').insertAdjacentHTML('beforeend', li);
document.getElementById('toDo').value = '';
}
First of all,
You should not use the same id for multiple elements. You are assigning id of "item" to every li element. So when you try to remove the element by id it will not work as expected.
Assign a unique id to every li element (you can also use unique classes or custom refs. But let's use ids).
<li id="some_unique_id">todo </li>
I think we will have to use classes and custom data attributes on the buttons to achieve what we want.
Ex: <button class="removeBtn" data-todoid="_the_corresponding_todo_id_">Remove</button>
Here we use the data-todoid attribute value to identify which li element will remove when we click this.
Let's modify your code now.
document.getElementById('myButton').onclick = function () {
// as we need some string or number to use as a unique id,
// its better to use the current timestamp in milliseconds in here.
const thiselementuniqueid = (new Date().getTime()).toString();
const doIt = document.getElementById('toDo').value;
const li = '<li id="todoitem_"+thiselementuniqueid >' + doIt + '<button type="button"
class="clearBtn" data-todoid="todoitem_"+thiselementuniqueid >X</button>' + '</li>';
document.getElementById('list').insertAdjacentHTML('beforeend', li);
document.getElementById('toDo').value = '';
// get all the li remove buttons
var clearButtons = getElementsByClassName('clearBtn');
// write on click event action for all of them
for(var a = 0; a<clearButtons.lenth;a++){
var asinglebutton = clearButtons[a]; // selected a button
asinglebutton.onClick = function(){
let todoid = $(this).data("todoid"); // get matching todo id to be removed on click
let currentLi = document.getElementById(todoid);
currentLi.removeChild();
}
}
document.getElementById('clearList').onclick = function() {
const ul = document.getElementById('list');
ul.innerHtml = "";
}
I haven't tested this. But this is the best approach in your case.
Edit : Leonardo's above answer is much simpler, easy, and quick. Try it.
I'm working on a project where I need to ask the user for an input and when the user clicks on the button the input get stored in local storage and displays on the screen, I want each time that the user gets on the page the input show off as a li element, but the problem is that the input shows off on the document only once, while refreshing the page, the li element disappears but the key and the value are still stored on the Local Storage.
Here's a part of my JavaScript.
const input = document.querySelector('#text-input');
const addBtn = document.querySelector('#add-plan-btn');
const ol = document.querySelector('ol');
addBtn.addEventListener('click', displayInput);
function displayInput(){
// this function shows the input on an li element
let li = document.createElement('li');
window.localStorage.setItem('plan', input.value);
li.textContent = localStorage.getItem('plan');
ol.appendChild(li);
}
here's my html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<div class="container">
<h1>Plan Maker</h1>
<div class="input-plan">
<input type="text" id="text-input" placeholder="enter here...">
<button type="submit" id="add-plan-btn">Add</button>
</div>
<ol></ol>
</div>
<script src="script.js"></script>
</body>
</html>
Thanks in advance.
First you need to save ol.innerText in local storage and on page load you may need to check if local storage has value, create some li based on storage value and append to ol tag
Try this one:
const input = document.querySelector('#text-input');
const addBtn = document.querySelector('#add-plan-btn');
const ol = document.querySelector('ol');
addBtn.addEventListener('click', displayInput);
var data = localStorage.getItem('plan');
if (data) {
var lst = data.split("\n");
lst.forEach(t => ol.innerHTML += "<li> " + t + "</li>");
}
function displayInput() {
// this function shows the input on an li element
let li = document.createElement('li');
li.textContent = input.value;
ol.appendChild(li);
window.localStorage.setItem('plan', ol.innerText);
}
I am doing a project where i need to make a todo list and then when a user clicks the add button itll pull the info in and create a new li item and it to my ul list. But i need my li's to be created with a checkbox attribute attached to them as well and i am stuck, My code is below
// this creates a new li based on the entered value in the text box that it gets when you hit the button
function addItem() {
let newLi = document.createElement("li");
let myLiValue = document.getElementById('textBoxAdd').value;
let liTextNode = document.createTextNode(myLiValue);
newLi.appendChild(liTextNode);
// this just makes sure a user cant enter in a blank value
if (myLiValue == "") {
alert("Please Enter Something Before Hitting Add Item");
} else {
document.getElementById('theNewList').appendChild(newLi);
document.getElementById('textBoxAdd').value = "";
}
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>To-Do List</title>
<link rel="stylesheet" href="main.css">
<script src="main.js" async></script>
</head>
<body>
<main>
<h1>Brody's Wonderful List Of Things</h1>
<h3>Enter a Item and Press "Add Item" to Add to Your List</h3>
<section>
<div class="">
<label>Please Enter in Your TODO Item</label>
<input type="text" id="textBoxAdd">
<button type="button" id="addBtn" onclick="addItem()">Add Item</button>
</div>
</section>
<section>
<ul id="theNewList">
</ul>
</section>
</main>
</body>
</html>
To add a checkbox you can use the following:
let newCheckBoxID = 'checkbox_' + myLiValue;
let newCheckBox = document.createElement("INPUT");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("id", newCheckBoxID);
newLi.appendChild(newCheckBox);
You'll notice I added code to give the checkbox an ID. Chances are that you'll want to use the value of the checkbox in code somewhere so making sure it has ID set would be necessary. For actual use you'll want to massage the myLiValue to not have spaces and whatnot first before you make it part of an id. Also, I would probably add that id to some array somewhere too as the checkboxes are created...
Next, I would consider putting your text in a LABEL tag instead of leaving it as raw text in the LI
let newCheckLabel = document.createElement('LABEL');
newCheckLabel.setAttribute('for', newCheckBoxID);
let labelTextNode = document.createTextNode(myLiValue);
newCheckLabel.appendChild(labelTextNode);
newLi.appendChild(newCheckLabel);
// this creates a new li based on the entered value in the text box that it gets when you hit the button
function addItem() {
let newLi = document.createElement("li");
let myLiValue = document.getElementById('textBoxAdd').value;
let newCheckBoxID = 'checkbox_' + myLiValue;
let newCheckBox = document.createElement("INPUT");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("id", newCheckBoxID);
newLi.appendChild(newCheckBox);
let newCheckLabel = document.createElement('LABEL');
newCheckLabel.setAttribute('for', newCheckBoxID);
let labelTextNode = document.createTextNode(myLiValue);
newCheckLabel.appendChild(labelTextNode);
newLi.appendChild(newCheckLabel);
// this just makes sure a user cant enter in a blank value
if (myLiValue == "") {
alert("Please Enter Something Before Hitting Add Item");
} else {
document.getElementById('theNewList').appendChild(newLi);
document.getElementById('textBoxAdd').value = "";
}
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>To-Do List</title>
<link rel="stylesheet" href="main.css">
<script src="main.js" async></script>
</head>
<body>
<main>
<h1>Brody's Wonderful List Of Things</h1>
<h3>Enter a Item and Press "Add Item" to Add to Your List</h3>
<section>
<div class="">
<label>Please Enter in Your TODO Item</label>
<input type="text" id="textBoxAdd">
<button type="button" id="addBtn" onclick="addItem()">Add Item</button>
</div>
</section>
<section>
<ul id="theNewList">
</ul>
</section>
</main>
</body>
</html>
There are posts where this is mentioned but in J Query which i have not learned yet. I have been trying to add the item once the user click on screen or keyboard. When the user clicks on screen it seems to be working perfectly but then when the user presses enter on keyboard, the items shows up for less than a millisecond then disappears. Also, if you can kindly mention how can I add a remove function to remove an item the user click on.
Here is the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Simple Shopping Cart</title>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<p class="buy">Buy your items anywhere and anytime</p>
<p class="click">click on an item to remove it</p>
<form>
<input type="text" class="item" placeholder="Item:">
<button type="button">Add item</button>
</form>
<br>
<ul>
</ul>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
and here is the JavaScript:
const input = document.querySelector(".item");
const btn = document.querySelector("button");
const ul = document.querySelector("ul");
function inputLength() {
return input.value.length;
}
function add() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
ul.appendChild(li);
}
function addItem() {
if (inputLength() > 0) {
add();
}
}
function addItemPress(event) {
if (inputLength() > 0 && event.which === 13) {
add();
}
}
btn.addEventListener("click", addItem);
input.addEventListener("keypress", addItemPress)
By default, forms will reset the page when they are submitted, unless you set the action property to "#". To run JavaScript when a form is submitted, you can use the onSubmit property. These approaches can be combined like this:
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Simple Shopping Cart</title>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<p class="buy">Buy your items anywhere and anytime</p>
<p class="click">click on an item to remove it</p>
<form id="addItemForm" action="#" onsubmit="add()">
<input type="text" class="item" placeholder="Item:">
<button type="submit">Add item</button>
</form>
<br>
<ul>
</ul>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
index.js:
const input = document.querySelector(".item");
const btn = document.querySelector("button");
const ul = document.querySelector("ul");
const form = document.getElementById("addItemForm");
function add() {
if (input.value.length > 0) {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
ul.appendChild(li);
form.reset();
}
}