Typescript DOM
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)