Emit Custom Events
Lesson objectives
The App.vue is responsible for showing the EventForm modal:
<EventForm :show="showModal" />
It also contains the event data to render in our app, stored inside the eventData array. Therefore we will also use this file to:
- Close the modal when the close button is clicked, or the user clicks off the modal area.
- Update the
eventDataarray with a new event from the form.
We will do this by making use of Vue.js custom events.
Closing the modal
Update the App.vue at the bottom of the script section:
const closeModal = () => {
showModal.value = false;
resetForm();
};
const resetForm = () => {
formData.value = {
name: "",
details: "",
date: "",
background: "linear-gradient(135deg, #FF416C, #FF4B2B)",
};
};
- The
closeModalfunction:- hides the modal by setting the
showModalvalue to false. - calls a second function called
resetForm.
- hides the modal by setting the
- The
resetFormfunction clears the values of all the form inputs.
This now leaves a small issue. The function to close the modal is located in the App.vue, and the buttons to call this function are inside the EventForm.vue:
<button class="close-button">×</button>
<button type="button" class="cancel-button">Cancel</button>
To solve this, we can use Vue.js custom events.
What are custom events
Custom events in Vue 3 provide a way for child components to communicate with their parent components. When a child component needs to notify its parent that something has happened, like a button click, form submission, or data update, it emits a custom event that the parent can listen for.
An example would be a function in the parent to show/hide visibility of a section, and this function can be called from a child component.
Listening for custom events
This works by a child component emitting an event, and a parent component listening for the event. Since the App.vue renders the EventForm component, this will be the parent > child relationship.
The parent App.vue listens for the custom event as an attribute. Update as follows:
<EventForm :show="showModal" @close="closeModal" />
- The
@close="closeModal"attribute listens for a custom event namedcloseemitted by theEventFormcomponent - When the
closeevent is emitted, it will call thecloseModalfunction we just created - The
@symbol is Vue's shorthand syntax forv-on: @closeis equivalent to writingv-on:close- This allows the child component (
EventForm) to communicate with the parent component (App.vue) by triggering the parent's function
Defining custom events
Over to the child component which is used to call (emit) the custom event. The Eventform currently defines which props the component should receive using defineProps():
<script setup>
const props = defineProps({
show: {
type: Boolean,
required: true,
},
});
</script>
In a similar way, we can also define which event the component should emit by using defineEmits():
<script setup>
const props = defineProps({
show: {
type: Boolean,
required: true,
},
});
// add
const emit = defineEmits(["close"]);
</script>
- The
defineEmitsfunction declares which custom events this component can emit to its parent - It takes an array of event names as strings,
["close"]means the component can emit acloseevent - The function returns an
emitfunction that we can use to actually trigger the event - This is similar to
defineProps- while props define what data flows down from parent to child,defineEmitsdefines what events flow up from child to parent
Emitting custom events
To actually emit the event, you would call emit("close") when needed.
<template>
<div v-if="show" class="modal-overlay">
<div class="modal">
<div class="modal-header">
<h2>Add New Event</h2>
<!-- emit the close event when clicked -->
<button class="close-button" @click="emit('close')">×</button>
Try this out in the browser, the x button should now close the form!
This can also be added to the modal-overlay wrapper to allow the modal to be closed when clicking off the main area:
<div v-if="show" class="modal-overlay" @click="emit('close')">
And also to the cancel button:
<button type="button" class="cancel-button" @click="emit('close')">
Cancel
</button>
Even though we have added the close event to specific elements, you will notice clicking anywhere on the modal will close it, we will resolve this in the next lesson.
Alternative syntax
Alternatively, emit('close') could also be called from inside a function:
const closeModal = () => {
emit("close");
};
Triggering the function when the button is clicked:
<button @click="closeModal" class="close-button">×</button>
This may be useful if you want to run some additional code before emitting the event.