<div id="todos">
  <form method="post" action="/my-backend-script">
    <input type="text" placeholder="What's next?" />
    <input type="submit" value="Add" />
  </form>
  <ul></ul>
</div>
#todos {
  font-family: sans-serif;
  color: #444;
}

/**
 * Todo List Input
 */
#todos form {
  display: flex;
}

#todos form input[type="text"],
#todos form input[type="submit"] {
  padding: 5px 10px;
  border: 1px solid #666;
  outline: none;
}

#todos form input[type="text"] {
  flex: 1;
}

#todos form input[type="text"]:focus {
  border-color: #369;
}

#todos form input[type="submit"] {
  margin-left: 5px;
  text-transform: uppercase;
}



/**
 * Todos List
 */

#todos ul {
  margin: 10px 0 0 0;
  padding: 0;
  border: 1px solid #ddd;
  border-radius: 4px;
}

#todos ul li {
  padding: 5px 10px;
  border-bottom: 1px solid #ddd;
  transition: background-color 500ms ease;
}

#todos ul li:last-child {
  border-bottom: none;
}

#todos ul li:hover {
  background-color: #cde;
}
/**
 * App's State
 */
const todos = [
  'buy milk',
  'clean kitchen',
  'learn js',
]

/**
 * High level render loop handler
 * instead of a huge complicated function,
 * we use sub-functions to delegate part of
 * the responsibilities and achieve a clear
 * and readable code
 */
const render = () => {
  resetDOMList()
  todos.forEach(renderDOMListItem)
}

const resetDOMList = () =>
  document
    .querySelectorAll('#todos ul *')
    .forEach($ => $.remove())

const renderDOMListItem = (item, index) => {
  const li = document.createElement('li')
  const txt = document.createTextNode(item)
  
  li.appendChild(txt)
  li.addEventListener('click', () => {
    todos.splice(index, 1)
    render()
  })
  
  document
     .querySelector('#todos ul')
     .appendChild(li)
}

/**
 * Form Handling
 */

const handleInput = (e) => {
  e.preventDefault()
  e.stopPropagation()
  
  // reference the text input from the form
  const textEl = e.target[0]
  
  // change app's state and rerender
  todos.push(textEl.value)
  render()
  
  // reset input
  textEl.value = ''
  textEl.focus()
}

document
  .querySelector('#todos form')
  .addEventListener('submit', handleInput)


/**
 * Run the first rendering loop
 * kinda "start the app" - kinda
 */
render()

Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.