I am working a small book-list app with Vue 3 and the composition API.
In App.vue I have:
<script setup>
import { ref } from 'vue'
import Book from './Book.vue'
import AddBook from './AddBook.vue'
const books = ref([])
const addBook = function(newBook) {
books.value.push(newBook);
}
</script>
<template>
<div class="container-fluid">
<h1 class="display-4">Reading list for 2024</h1>
<ol v-if="books.length" class="books">
<Book v-for="(book, index) in books" :book="{
title: book.title,
author: book.author
}" />
</ol>
<p class="text-center" v-else>No books to display</p>
<AddBook @add-book="addBook" />
</div>
</template>
In Book.vue
I have:
<script setup>
defineProps({
book: Object
})
</script>
<template>
<li>
<i>{{ book.title }}</i> by {{ book.author }}
<span class="delete" @click="$emit('delete-book', index)">✖</span>
</li>
</template>
The form for adding a book is in AddBook.vue
:
<script setup>
import { ref, defineEmits } from 'vue'
const emit = defineEmits(['add-book'])
const isValid = ref(true);
const newBook = {
title: '',
author: ''
}
const handleSubmit = function(){
isValid.value = false;
if(newBook.title.length && newBook.author.length){
isValid.value = true;
emit('add-book', newBook);
}
}
</script>
<template>
<h2 class="display-4">Add a book</h2>
<form @submit.prevent="handleSubmit">
<div v-if="!isValid" class="p-2 text-center alert alert-danger">
The form data is invalid!
</div>
<div class="mb-2">
<label for="title" class="form-label">Title</label>
<input id="title" class="form-control form-control-sm" type="text" v-model="newBook.title">
</div>
<div class="mb-2">
<label for="author" class="form-label">Author</label>
<input id="author" class="form-control form-control-sm" type="text" v-model="newBook.author">
</div>
<div class="mb-2">
<button class="btn btn-sm btn-success w-100" type="submit">Add</button>
</div>
</form>
</template>
After adding a book, I want the form fields to be cleared.
Doing this in order to achieve the goal does clear the fields, but it also empties the title
and author
properties of the newBook
object:
emit('add-book', newBook);
// Clear fields
newBook.title = '',
newBook.author = ''
The problem is that newBook
is cleared before the parent component has a change to access it.
You could create a copy of the newBook
object before emitting:
<script setup>
import { ref, defineEmits } from 'vue'
const emit = defineEmits(['add-book']);
const isValid = ref(true);
const newBook = {
title: '',
author: ''
}
const handleSubmit = function(){
isValid.value = false;
if(newBook.title.length && newBook.author.length){
isValid.value = true;
// Create a copy of newBook before emitting
const bookCopy = { ...newBook };
emit('addBook', bookCopy);
// Clear the original newBook object
newBook.author = '';
newBook.title = '';
}
}
</script>