I’m working on a shopping cart using vue3 with inertiajs and Laravel and page layout demands to have a main menu with a bag button which on click fires showing and hiding cart event. So as menu and cart are children component from main page, I guess that the goal is by using communication between components. I’ve read emit documentation and I can get it working from parent to child and from child to parent, but I can’t achieve the communication between both children components.
I have the following code:
Parent
<Cart :isVisible="showCart" @hideCart="showCart = false" />
<script>
export default {
data() {
return {
showCart: false,
}
},
methods: {
toggleCart() {
this.showCart = !this.showCart
},
}
}
</script>
Menu
<button @click="$emit('toggleCart')"><Icon name="bag" /></button>
Cart
<template>
<div v-if="isVisible">
<h3 >
<span >My cart</span>
<button @click="$emit('toggleCart')" >×</button>
</h3>
...html code for cart
</div>
</template>
<script setup>
import { Link } from "@inertiajs/inertia-vue3";
const props = defineProps(["isVisible", "cart"]);
const emit = defineEmits(["toggleCart"]);
</script>
CodePudding user response:
$emit
doesn't call a method in the parent, you have to handle the $emitted event yourself, usually by calling a method. So in your parent component you should have:
<template>
<Cart :isVisible="showCart" @toggle-cart="toggleCart"..... />
<Menu @toggle-cart="toggleCart" ..... />
</template>
<script>
//...
methods: {
toggleCart() {
this.showCart = !this.showCart
},
//...
</script>
The @toggle-cart=
is referring to the emitted event, the "toggleCart"
is referring to the method in your parent component, but there's no need for them to have the same name. You could have @toggle-cart="handleCartToggle"
as long as handleCartToggle
is your method name.
(Note: The kebab-case @toggle-cart
instead of @toggleCart
is how Vue recommends you refer to events in the template, to align with HTML attributes. Still use toggleCart
in the Cart component.