0

The finished product is just supposed to have a checkbox next to each entry, and the option to edit or delete each item. I'm nowhere near that as I can't even get an item to post.

Here's are the files that I have: HTML, CSS, JS.

Also, I'm sorry for the formatting.I didn't paste the CSS as that's not an issue as far as I'm concerned.

HTML:

var list = document.getElementById('list'); //The unordered list.
var entry = document.createElement("li"); //Whatever this is. I'm assuming a command saved into a variable (?).

//var todolist = list.getElementsById('li');
// var btn = document.getElementById('ToDoButton');
//
// btn.addEventListener("click", function(){
//     todolist.appendChild('li');
// });

/* Upon submission of the item in the text field, the string is stored in inputValue
and theText becomes a text node of inputValue, which is appended to the end of the variable
entry. This means that there should be a new item added to the unordered list with the information
found in the text field, but it doesn't show.
    
Also, as far as I know, this is only if the Add button is clicked, and not upon
pressing Enter while in the text box. */
function newElement() {
  var inputValue = document.getElementById("textBox").value;
  var theText = document.createTextNode(inputValue);
  entry.appendChild(theText);
  if (inputValue !== '') {
    document.getElementById(list).appendChild(entry);
  }
}
<!DOCTYPE html>
<html>

<head>
  <title>To-Do List</title>
  <link rel="stylesheet" href="todo.css">
</head>

<body>
  <div class="toDoList">
    <h4>To-Do List</h4>
    <form target="_self">
      <!-- This is so that the submitted information doesn't go anywhere but to the current page. -->
      <input type="text" name="toDoList" placeholder="To-Do" id="textBox">
      <input type="submit" value="Add" onclick="newElement()" id="ToDoButton">
      <!-- newElement() is a JS function that will add the information in the search bar to the unordered list below. -->
    </form>
  </div>
  <section id="main">
    Tasks:
    <ul id="list">
      <!-- These are dummy values for the unordered list. The idea
                    is that the next item should be placed beneath them. -->
      <li>test1</li>
      <li>test2</li>
      <li>test3</li>
    </ul>
  </section>
  <script type="text/javascript" src="todo.js">
  </script>
</body>

</html>
j08691
  • 204,283
  • 31
  • 260
  • 272
pikecha
  • 41
  • 2
  • 1
    you are submitting a form, does that cause the page to reload? – Isaac Vidrine Mar 04 '19 at 21:25
  • Possible duplicate of [How to prevent default on form submit?](https://stackoverflow.com/questions/17709140/how-to-prevent-default-on-form-submit) – Mouser Mar 04 '19 at 21:27
  • `document.createElement` will create an element *in memory*, but it won't render until you append it to the DOM. You need to append `entry` to the DOM somehow, i.e. as a child of the body or a child of the element with ID "main", etc. You also don't want to submit a form, as ^ they have said. Use a button-type input instead of a submit-type input for this. (Honestly, you already have a list with an ID of "list" -- just append the new items to that instead of creating "entry" needlessly.) – IceMetalPunk Mar 04 '19 at 21:28
  • @IsaacVidrine, indeed that had happened. I guess I didn't know what to expect in doing this and thought that it would reload with the changes. Another answer on here has brought about that that's not what I should have. – pikecha Mar 04 '19 at 21:44
  • @IceMetalPunk, I thought that I was appending `entry` per the third-to-last line of code in the JS file. I get that appending to the `
      ` tag doesn't work, but I don't understand why it doesn't. Good point about not needlessly creating new variables -- thank you. I'm a sloppy coder.
    – pikecha Mar 04 '19 at 21:48
  • A few issues with that. Your `list` variable is the result of `document.getElementById("list")` -- but you're wrapping that in another `document.getElementById` call. That won't work because that function expects a string ID, not an already-resolved element. Secondly, you don't want to append the entry list to a list -- that's nesting two lists which you don't want (probably). You also don't need to append the entry list to the DOM every time you update it; just append it once and then whenever you append a list item, it'll automatically update the DOM. But you don't need the entry list anyway – IceMetalPunk Mar 04 '19 at 21:52
  • (Continued) Just append the list items directly to your list element, no need to create a new one in the entry variable. – IceMetalPunk Mar 04 '19 at 21:52

3 Answers3

0

This is a short example of how to dynamically add elements on the page. User types in a to do item, then clicks the button. When they click the button, we get the value from the input box, create a new list item element, and then append it to the dom.

function addItem() {
  var el = document.createElement('li')
  var val = document.getElementById('item-val').value;
  el.innerHTML = val;
  document.getElementById('list').append(el);
}
<input id="item-val" type="text" />
<button onclick="addItem()">Add an item</button>
<ul id="list"></ul>
Isaac Vidrine
  • 1,568
  • 1
  • 8
  • 20
0

A few problems:

1) When you click the button, it submits the form. This causes your page to refresh, so any and all changes made by the JavaScript are lost, because you re-load the page from the server. Changing it to <button type="button" means it doesn't cause a postback any more. To be honest you probably don't actually need <form> here at all if you aren't going to send the data to the server.

2) Better to put your list and entry variables inside the function - globals are best avoided if you can, to reduce accidental scope issues. Also you need to create a new entry each time, not keep appending the same one.

3) document.getElementById(list).appendChild(entry) doesn't work because list is already an object representing an element - it's not a string containing an ID. so list.appendChild() is correct here - i.e. you can just call the appendChild() function on the existing object directly.

4) Optionally, you don't really need the separate textNode object - just set the innerText property of the list item instead.

5) Optionally again, but considered best practice: I declared an unobtrusive event handler (using addEventListener) rather than putting it inline inside the HTML. This is generally considered to make the code more maintainable and traceable, as all the script is held in one place, separate from the HTML.

Here's a fixed version:

document.querySelector("#ToDoButton").addEventListener("click", newElement);

/* Upon submission of the item in the text field, the string is stored in inputValue
and theText becomes a text node of inputValue, which is appended to the end of the variable
entry.*/

function newElement() {
  var list = document.getElementById('list'); //The unordered list.
  var entry = document.createElement("li"); //a new list item
  var inputValue = document.getElementById("textBox").value;
  
  if (inputValue !== '') {
    entry.innerText = inputValue;
    list.appendChild(entry);
  }
}
<!DOCTYPE html>
<html>

<head>
  <title>To-Do List</title>
  <link rel="stylesheet" href="todo.css">
</head>

<body>
  <div class="toDoList">
    <h4>To-Do List</h4>
    <form target="_self">
      <input type="text" name="toDoList" placeholder="To-Do" id="textBox">
      <button type="button" id="ToDoButton">Add</button>
    </form>
  </div>
  <section id="main">
    Tasks:
    <ul id="list">
      <!-- These are dummy values for the unordered list. The idea
                    is that the next item should be placed beneath them. -->
      <li>test1</li>
      <li>test2</li>
      <li>test3</li>
    </ul>
  </section>
  <script type="text/javascript" src="todo.js">
  </script>
</body>

</html>
ADyson
  • 57,178
  • 14
  • 51
  • 63
  • Thank you very much for your response. I have a few further questions: 2) Someone pointed out that rather than making a variable `entry`, to just type what it refers to, i.e. `document.createElement("li")`. Would doing so lead to the same problem of reusing the same object/element/whatever-the-term-may-be? 3) I guess I incorrectly used the apostrophes there. I intended to use the quotation to refer to the `id` attribute similarly to how it's done with other tags. `list` wouldn't be an `id`, but `"list"` is. That should be fine, right? 5) I had something like that earlier! Thank you! – pikecha Mar 04 '19 at 21:57
  • 2) It wouldn't result in problems with re-using the same thing - you create a new item each time you run the command. But not sure you should drop `entry` entirely - it's referred to in (my) code, and you need to append it to the list. Not sure what was meant by that remark. 3) Yeah "list" would be fine inside a document.getElementById, but actually since you already created the `list` variable to refer to that element, you might as well use that - more efficient to use an existing reference than create a new one. – ADyson Mar 04 '19 at 22:26
  • Anyway, if my answer has fixed your issue, please remember to mark it as "accepted" (click the tick mark next to the answer so it turns green) - thanks :) – ADyson Mar 04 '19 at 22:27
0

Your main issue is that you were using and <input type="submit"> when you were expecting the behavior of <input type="button"> with a click event listener:

document.querySelector('#ToDoButton').addEventListener('click', newElement);

function newElement() {
  var inputValue = document.getElementById("textBox").value;
  var theText = document.createTextNode(inputValue);
  var liEl = document.createElement('li');

  liEl.appendChild(theText);
  if (inputValue !== '') {
    document.getElementById('list').appendChild(liEl);
  }
}
<head>
  <title>To-Do List</title>
  <link rel="stylesheet" href="todo.css">
</head>

<body>
  <div class="toDoList">
    <h4>To-Do List</h4>
    <input type="text" name="toDoList" placeholder="To-Do" id="textBox">
    <!--The input type needs to be "button, not "submit"-->
    <input type="button" value="Add" id="ToDoButton">
  </div>
  <section id="main">
    Tasks:
    <ul id="list">
      <li>test1</li>
      <li>test2</li>
      <li>test3</li>
    </ul>
  </section>
  <script type="text/javascript" src="todo.js">
  </script>
</body>
Tom O.
  • 5,730
  • 2
  • 21
  • 35