Home > Mobile >  Hard stuck for 3 days in a simple to do list
Hard stuck for 3 days in a simple to do list

Time:10-13

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.

CodePudding user response:

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>

CodePudding user response:

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.

CodePudding user response:

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>

CodePudding user response:

  1. 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.
  2. <script> tag shouldn't have href attribute. It should be src instead.
  3. 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 = '';
})

CodePudding user response:

I changed your code. The problems are 3 in number.

  1. 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)
  2. you made toDoStuff get the value of the input thus overriding the create element.
  3. 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!

CodePudding user response:

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 ></ul>
</main>

  • Related