Skip to main content

Typescript DOM

TST, Hongkong

Setup

Build the obligatory TODO List

Use the same setup as above but instead of running the compiled JS file inside Node.js it will now be embedded inside an HTML file and executed inside a web browser:

./dist/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Typescript DOM Project</title>
  </head>
  <body>
    <header></header>
    <main>
      <input id="input" type="text" placeholder="Enter a TODO!">
      <button id='clickme'>Use Input Value!</button>
    </main>
    <footer></footer>
    <script type="module" src="index.js"></script>
  </body>
</html>

./src/index.ts

const btn = document.getElementById('clickme') as HTMLButtonElement
const input = document.getElementById('input') as HTMLInputElement

btn?.addEventListener('click', function(){
    console.log(input.value)
    input.value = ''
})

Adding a Form element with submit event listener:

./src/index.ts

const btn = document.getElementById('submit') as HTMLButtonElement
const input = document.querySelector<HTMLInputElement>('#input')!
const form = document.querySelector<HTMLFormElement>('#form')
const list = document.getElementById('list') as HTMLUListElement

function handleSubmit(e: SubmitEvent) {
    e.preventDefault()
    console.log(`INFO :: New TODO ${input.value}`)

    const todoText = input.value
    const newListElement = document.createElement('li')
    const checkBox = document.createElement('input')
    checkBox.type = 'checkbox'

    newListElement.append(todoText)
    newListElement.append(checkBox)
    list?.append(newListElement)
    input.value = ''
}

form?.addEventListener('submit', handleSubmit)

./dist/index.html

<body>
    <header><h1>TODO List</h1></header>
    <main>
      <ul id="list"></ul>
      <form id="form" action="">
        <input id="input" type="text" placeholder="Enter a TODO!">
        <button id='submit' type="submit">Add</button>
      </form>
    </main>
    <footer><code><small>Build with Typescript</small></code></footer>
    <script src="index.js"></script>
  </body>

To add list items to local browser storage first start by writing all todos to an todos array on creation:

./src/index.ts

interface Todo {
    text: string
    completed: boolean
}

const todos: Todo[] = []

const btn = document.getElementById('submit') as HTMLButtonElement
const input = document.querySelector<HTMLInputElement>('#input')!
const form = document.querySelector<HTMLFormElement>('#form')
const list = document.getElementById('list') as HTMLUListElement


function handleSubmit(e: SubmitEvent) {
    e.preventDefault()
    console.log(`INFO :: New TODO ${input.value}`)

    const todo: Todo = {
        text: input.value,
        completed: false
    }

    createTodo(todo)
    todos.push(todo)

}

const createTodo = (todo: Todo) => {
    const newListElement = document.createElement('li')
    const checkBox = document.createElement('input')
    checkBox.type = 'checkbox'

    newListElement.append(todo.text)
    newListElement.append(checkBox)
    list?.append(newListElement)
    input.value = ''
}

form?.addEventListener('submit', handleSubmit)

The todos array can now be written to localStorage and re-instantiated from storage on a page re-load using the createTodo function:

./src/index.ts

const getStoredTodos = (): Todo[] => {
    const storedTodos = localStorage.getItem('todos')

    if (storedTodos === null) {
        return []
    } else {
        return JSON.parse(storedTodos)
    }
}


const createTodo = (todo: Todo) => {
    const newListElement = document.createElement('li')
    const checkBox = document.createElement('input')
    checkBox.type = 'checkbox'

    newListElement.append(todo.text)
    newListElement.append(checkBox)
    list?.append(newListElement)
    input.value = ''
}


const todos: Todo[] = getStoredTodos()
todos.forEach(createTodo)



const handleSubmit = (e: SubmitEvent) => {
    e.preventDefault()
    console.log(`INFO :: New TODO ${input.value}`)

    const todo: Todo = {
        text: input.value,
        completed: false
    }

    createTodo(todo)
    todos.push(todo)

    localStorage.setItem("todos", JSON.stringify(todos))
}

This handles the text for all Todos but so far ignores the completion status and todos cannot be deleted:

./src/index.ts

interface Todo {
    text: string
    completed: boolean
}

const btn = document.getElementById('submit') as HTMLButtonElement
const input = document.querySelector<HTMLInputElement>('#input')!
const form = document.querySelector<HTMLFormElement>('#form')
const list = document.getElementById('list') as HTMLUListElement


const getStoredTodos = (): Todo[] => {
    const storedTodos = localStorage.getItem('todos')

    if (storedTodos === null) {
        return []
    } else {
        return JSON.parse(storedTodos)
    }
}


const createTodo = (todo: Todo) => {
    const newListElement = document.createElement('li')
    const deleteButton = document.createElement('button')
    const checkBox = document.createElement('input')
    checkBox.type = 'checkbox'
    checkBox.checked = todo.completed

    deleteButton.addEventListener('click', function() {
        todos = todos.filter(value => value !== todo)
        saveTodos()
    }) 

    checkBox.addEventListener('change', function() {
        todo.completed = checkBox.checked
        saveTodos()
    })

    newListElement.append(todo.text)
    newListElement.append(checkBox)
    newListElement.append(deleteButton)
    list?.append(newListElement)
    input.value = ''
}


const saveTodos = () => {
    localStorage.setItem("todos", JSON.stringify(todos))
}


const handleSubmit = (e: SubmitEvent) => {
    e.preventDefault()
    console.log(`INFO :: New TODO ${input.value}`)

    const todo: Todo = {
        text: input.value,
        completed: false
    }

    createTodo(todo)
    todos.push(todo)

    saveTodos()
}


form?.addEventListener('submit', handleSubmit)


let todos: Todo[] = getStoredTodos()
todos.forEach(createTodo)