Skip to content

Instantly share code, notes, and snippets.

@thepassle
Created January 30, 2021 12:48
Show Gist options
  • Save thepassle/dbaa29eac687bcefb4889a73483839ec to your computer and use it in GitHub Desktop.
Save thepassle/dbaa29eac687bcefb4889a73483839ec to your computer and use it in GitHub Desktop.
<html>
<body>
<form id="todoInput">
<input type="text" name="todo"></input>
<button type="submit">submit</button>
</form>
<ul id="todoList">
</ul>
<script>
// This will be a placeholder to store our todos, this is a `let` variable because a user might delete a todo
let todos = [];
// We need to keep track of an index for our todos, so we know which one to delete
let id = 0;
// Get a reference to the <form> element
const form = document.getElementById("todoInput");
// Get a reference to the todoList <ul>
const todoList = document.getElementById("todoList");
// This function will construct the HTML that we want to 'render' in our unordered list
// This is its own function because we'll need to reuse it multiple times
function constructListHTML() {
let todolistHtml = '';
todos.forEach(todoItem => {
todolistHtml += `
<li>
<input type="checkbox"></input>
<span>${todoItem.value}</span>
<button id="${todoItem.id}">❌</button>
</li>
`;
});
return todolistHtml;
}
/**
* We add an eventListener (a creeper) to the form event so that whenever the form has been
* 'submitted', we can execute some JavaScript. In this case, we want to construct a new
* todo object with a `value` and an `id`.
*
* Then we want to construct the HTML we need to render the list, and set the todoList's
* innerHTML value to the list we want to render.
*/
form.addEventListener("submit", (event) => {
event.preventDefault();
todos.push({
value: event.target.elements["todo"].value,
id: id
});
todoList.innerHTML = constructListHTML();
// Finally, dont forget to increment the ID so it'll always be unique :)
id++;
});
/**
* Here we add a click event listener to the unordered list. The unordered list by itself is not
* an interactive element, but we use a clever trick called 'event delegation'.
*
* The unordered list element will listen to any click events from any of its children. In this
* case, we're only interested in HTML tags that are <button>s.
*/
todoList.addEventListener("click", (event) => {
if(event.target.tagName === 'BUTTON') {
// If we know the click event came from a button, we want to get its ID, and make sure we parse it as an integer!
const id = parseInt(event.target.id);
// Then we want to _filter_ out the todoItem with the `id`, this essentially creates a new array
// and assigns it to our `todos` variable, but the item we want to delete has been removed from it.
todos = todos.filter(todoItem => {
return todoItem.id !== id;
});
// And finally, we want to reconstruct our HTML again, and 'render' it.
todoList.innerHTML = constructListHTML();
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment