CRUD Operations
Adding new tasks
Now that we can see the list of tasks, it's time to add a few more.
Add the highlighted newTaskTitle
state and addTask
function the Home Component
// src/components/Todo.tsx
export default function Todo() {
const [tasks, setTasks] = createStore<Task[]>([])
const [newTaskTitle, setNewTaskTitle] = createSignal("")
async function addTask(e: Event) {
e.preventDefault()
try {
const newTask = await taskRepo.insert({ title: newTaskTitle() })
setTasks([...tasks, newTask])
setNewTaskTitle("")
} catch (error) {
alert((error as { message: string }).message)
}
}
//...
Import createSignal
This code requires adding an import of createSignal
from solid-js
.
- the call to
taskRepo.insert
will make a post request to the server, insert the new task to thedb
, and return the newTask
object with all it's info (including the id generated by the database)
Next let's adjust the tsx
to display a form to add new tasks
// src/components/Todo.tsx
return (
<main>
<form onSubmit={addTask}>
<input
value={newTaskTitle()}
placeholder="What needs to be done?"
onInput={(e) => setNewTaskTitle(e.currentTarget.value)}
/>
<button>Add</button>
</form>
<For each={tasks}>
{(task) => {
return (
<div>
<input type="checkbox" checked={task.completed} />
{task.title}
</div>
)
}}
</For>
</main>
)
Try adding a few tasks to see how it works
Mark Tasks as completed
Modify the contents of the For
iteration within the Todo
component to include the following setCompleted
function and call it in the input'sonInput
event.
// src/components/Todo.tsx
<For each={tasks}>
{(task, i) => {
async function setCompleted(completed: boolean) {
const updatedTask = await taskRepo.update(task, { completed })
setTasks(i(), updatedTask)
}
return (
<div>
<input
type="checkbox"
checked={task.completed}
oninput={(e) => setCompleted(e.target.checked)}
/>
{task.title}
</div>
)
}}
</For>
- The
taskRepo.update
method updates thetask
to the server and returns the updated value
Rename Tasks and Save them
To make the tasks in the list updatable, we'll bind the tasks
solid state to input
elements and add a Save button to save the changes to the backend database.
Modify the contents of the For
iteration within the Todo
component to include the followingsetTitle
andsaveTask
functions and add aninput
and a savebutton
.
// src/components/Todo.tsx
<For each={tasks}>
{(task, i) => {
async function setCompleted(completed: boolean) {
const updatedTask = await taskRepo.update(task, { completed })
setTasks(i(), updatedTask)
}
async function saveTask() {
try {
await taskRepo.save(task)
} catch (error) {
alert((error as { message: string }).message)
}
}
return (
<div>
<input
type="checkbox"
checked={task.completed}
oninput={(e) => setCompleted(e.target.checked)}
/>
<input
value={task.title}
onInput={(e) => setTasks(i(), "title", e.target.value)}
/>
<button onClick={saveTask}>Save</button>
</div>
)
}}
</For>
- The
saveTask
function, called from thebutton
's'onClick
event , saves thetask
object to the backend.
Make some changes and refresh the browser to verify the backend database is updated.
Browser's Network tab
As you play with these CRUD
capabilities, monitor the network tab and see that they are all translated to rest
api calls.
Delete Tasks
Let's add a Delete button next to the Save button of each task in the list.
Add the highlighted deleteTask
function and Delete button
Within the For
iteration in the return
section of the Todo
component.
// src/components/Todo.tsx
<For each={tasks}>
{(task, i) => {
async function setCompleted(completed: boolean) {
const updatedTask = await taskRepo.update(task, { completed })
setTasks(i(), updatedTask)
}
async function saveTask() {
try {
await taskRepo.save(task)
} catch (error) {
alert((error as { message: string }).message)
}
}
async function deleteTask() {
try {
await taskRepo.delete(task)
setTasks(tasks.filter((t) => t !== task))
} catch (error) {
alert((error as { message: string }).message)
}
}
return (
<div>
<input
type="checkbox"
checked={task.completed}
oninput={(e) => setCompleted(e.target.checked)}
/>
<input
value={task.title}
onInput={(e) => setTasks(i(), "title", e.target.value)}
/>
<button onClick={saveTask}>Save</button>
<button onClick={deleteTask}>Delete</button>
</div>
)
}}
</For>