# CRUD Operations

# Rename Tasks and Mark as Completed

To make the tasks in the list updatable, we'll bind the input elements to the Task properties and add a Save button to save the changes to the backend database.

src/App.vue
















 
 
 
 








 
 





<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { remult } from 'remult';
import { Task } from './shared/Task';

const taskRepo = remult.repo(Task);
const tasks = ref<Task[]>([]);
const hideCompleted = ref(false);
async function fetchTasks() {
  tasks.value = await taskRepo.find({
    limit: 20,
    orderBy: { completed: "asc" },
    where: { completed: hideCompleted.value ? false : undefined }
  });
}
async function saveTask(task: Task) {
  const savedTask = await taskRepo.save(task);
  tasks.value = tasks.value.map(t => t === task ? savedTask : t);
}
onMounted(() => fetchTasks())
</script>
<template>
  <div>
    <input type="checkbox" v-model="hideCompleted" @change="fetchTasks()" /> Hide Completed
    <main>
      <div v-for="task in tasks">
        <input type="checkbox" v-model="task.completed" />
        <input v-model="task.title" />
        <button @click="saveTask(task)">Save</button>
      </div>
    </main>
  </div>
</template>

Why update the task array after saving a task?

Remult's Repository.save method issues either a PUT or a POST request, depending on the existence of an id value in the Task object.

In the next section of the tutorial, we'll add new tasks to the list by creating Task objects and saving them using the same saveTask function. So, to make sure a newly created task is only POST-ed once, we must replace it with the return value of Repository.save, which contains an id.

After the browser refreshes, the tasks can be renamed and marked as completed.

Make some changes and refresh the browser to verify the backend database is updated.

# Add New Tasks

Add the highlighted addTask function and Add Task button to the App component:

src/App.vue




















 
 
 












 



<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { remult } from 'remult';
import { Task } from './shared/Task';

const taskRepo = remult.repo(Task);
const tasks = ref<Task[]>([]);
const hideCompleted = ref(false);
async function fetchTasks() {
  tasks.value = await taskRepo.find({
    limit: 20,
    orderBy: { completed: "asc" },
    where: { completed: hideCompleted.value ? false : undefined }
  });
}
async function saveTask(task: Task) {
  const savedTask = await taskRepo.save(task);
  tasks.value = tasks.value.map(t => t === task ? savedTask : t);
}
function addTask() {
  tasks.value.push(new Task());
}
onMounted(() => fetchTasks())
</script>
<template>
  <div>
    <input type="checkbox" v-model="hideCompleted" @change="fetchTasks()" /> Hide Completed
    <main>
      <div v-for="task in tasks">
        <input type="checkbox" v-model="task.completed" />
        <input v-model="task.title" />
        <button @click="saveTask(task)">Save</button>
      </div>
    </main>
    <button @click="addTask()">Add Task</button>
  </div>
</template>

Add a few tasks and refresh the browser to verify the backend database is updated.

Note

New tasks will not be saved to the backend until you press the Save button.

# 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 tasks.map iteration in the return section of the App component.

src/App.vue























 
 
 
 










 






<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { remult } from 'remult';
import { Task } from './shared/Task';

const taskRepo = remult.repo(Task);
const tasks = ref<Task[]>([]);
const hideCompleted = ref(false);
async function fetchTasks() {
  tasks.value = await taskRepo.find({
    limit: 20,
    orderBy: { completed: "asc" },
    where: { completed: hideCompleted.value ? false : undefined }
  });
}
async function saveTask(task: Task) {
  const savedTask = await taskRepo.save(task);
  tasks.value = tasks.value.map(t => t === task ? savedTask : t);
}
function addTask() {
  tasks.value.push(new Task());
}
async function deleteTask(task: Task) {
  await taskRepo.delete(task);
  tasks.value = tasks.value.filter(t => t !== task);
}
onMounted(() => fetchTasks())
</script>
<template>
  <div>
    <input type="checkbox" v-model="hideCompleted" @change="fetchTasks()" /> Hide Completed
    <main>
      <div v-for="task in tasks">
        <input type="checkbox" v-model="task.completed" />
        <input v-model="task.title" />
        <button @click="saveTask(task)">Save</button>
        <button @click="deleteTask(task)">Delete</button>
      </div>
    </main>
    <button @click="addTask()">Add Task</button>
  </div>
</template>