To Do List (Example)
Overview
This example will cover a form-based app that handles both GET and POST http methods.
- GET method: show the list of TODO tasks
- POST method: adding/deleting tasks
Setup
We assume you have created the starter app.
Within that app, create a new file pages/todo.tht
.
Copy and paste each code snippet below into the file.
Main Function
The main function is called by default, when the page is requested via http GET (i.e. when a form is not submitted.)
function main() { $tasks = getTasks(); Response.sendPage({ body: bodyHtml($tasks), css: Css.plugin('base'), }); }
Data Functions
We will read and write the list of tasks to the user’s Session. The Session will be cleared when the user closes the browser tab.
(In a real app, you would read and write data to a database using the Db
module.)
function getTasks() { // Default to an empty list if there are no tasks return Session.get('tasks', []); } function setTasks($tasks) { Session.set('tasks', $tasks); } function addTask($task) { $tasks = getTasks(); tasks.push($task); setTasks($tasks); } function deleteTask($taskNum) { $tasks = getTasks(); $tasks.remove($taskNum); setTasks($tasks); }
Mode Functions
If the request has a POST parameter named mode
, THT will automatically call the corresponding function instead of main
.
The Input.post
method reads the POST param and validates it per the rule defined in the 2nd argument.
// If POST mode='delete' function modeDelete() { // 'taskNum' is an (i)nteger $taskNum = Input.post('taskNum', 'i'); deleteTask($taskNum); return true; } // If POST mode='add' function modeAdd() { // 'task' is a (s)tring $task = Input.post('task', 's'); if $task { addTask($task); } return true; }
Templates
The Web.formLink
method creates a button that submits data (via a form with hidden fields), without the need for AJAX.
Styles are separated into a css
template function. It will be minified and included inline.
function deleteButton($num) { $data = { mode: 'delete', taskNum: $num }; return Web.formLink('X', url'/todo', $data, 'button-small'); } template bodyHtml($tasks) { <main> {{ taskFormHtml() }} <hr /> {{ taskListHtml($tasks) }} </> {{ pageCss() }} } template taskFormHtml() { <h2>New Task</> <form method="post" action="/todo"> <input type="hidden" name="mode" value="add" /> <input type="text" name="task" /> <button type="submit">{{ Web.icon('plus') }} Add Task</> </> } template taskListHtml($tasks) { <h2>Tasks</> -- if !$tasks.length() { <i>No tasks.</> -- } else { -- foreach $tasks as $num, $task { <div class="task"> {{ $task }} {{ deleteButton($num) }} </> -- } -- } } template pageCss() { .task { border-bottom: solid 1px #eee; padding: 1.2rem 1rem; position: relative; } .task form { position: absolute; right: 0; top: 0.8rem; } }