Can child components forward specific events to their parent component?

I created a basic component that triggers events whenever a button is clicked.

InnerComponent.vue

<template>
  <v-btn @click="emit('something-happened')">Click me</v-btn>
</template>

<script setup lang="ts">
const emit = defineEmits<{ (e: 'something-happened'): void }>()
</script>

This component is used by a container component that doesn't prioritize the event but its parent component does. Currently, I handle the event and trigger it again as follows-

OuterComponent.vue

<template>
  <inner-comp @something-happened="onSomethingHappened" />
</template>

<script setup lang="ts">
import InnerComp from "./InnerComp.vue";
  
const emit = defineEmits<{ (e: 'something-happened'): void }>()

function onSomethingHappened() {
  emit("something-happened");
}
</script>

The parent component handles the event-

App.vue

<template>
  <v-app>
    <v-main>
      <outer-comp @something-happened="onSomethingHappened" />
    </v-main>
  </v-app>
</template>

<script setup lang="ts">
import OuterComp from "./OuterComp.vue";

function onSomethingHappened() {
  console.log("something happened");
}
</script>

Is there a way to simplify the code in OuterComponent?
This component requires some boilerplate code to pass the event back to its parent. While it's necessary for this component to define emits for proper TypeScript support, perhaps there is a shortcut syntax to quickly "bubble" the event e.g.

<inner-comp @something-happened.direct-forward="onSomethingHappened" />

For demonstration purposes- See here

Answer №1

If you're searching for a way to pass attributes in Vue 3, consider using v-bind="$attrs". In Vue 3, Vue events are now treated as attributes with the prefix on, eliminating the need for declaring them separately as $listeners like in Vue 2 (you can read more about this change here):

Here is an example of how to use it:

<template>
  <div>
    <inner-comp v-bind="$attrs" />
  </div>
</template>
<script>
  export default {
    inheritAttrs: false
  }
</script>

The line inheritAttrs: false indicates that Vue should not bind attributes to the outer <div>. Instead, v-bind="$attrs" binds them directly to one or more inner elements without specifying each attribute individually.


If you have a mix of attributes that you want to pass and some that you don't, you can group them into objects like so:

<inner-comp v-bind="$attrs.foo" />

In this case, foo would represent an object containing the desired attributes:

<outer-comp :foo="{ onSomethingHappened }" />

Answer №2

If you're working with Vue 3, there's a fantastic library called VueUse that provides useful utility composables. One such composable is useEventBus, which allows you to work with an event bus independently of the component structure.

MainApp.vue

// Inside script setup
const somethingBus = useEventBus<string>('something');

const listener = (event: string) => {
console.log(`news: ${event}`)
}

const unsubscribe = somethingBus.on(listener)

InnerComponent.vue

// Inside script setup
const somethingBus = useEventBus<string>('something');

const handleClick = () => {
somethingBus.emit('Some Value')
}

If you're using TypeScript, you can create a symbol with the type EventBusKey to serve as the event bus key. Check out the documentation for more information.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering TS 2694 Error while running the ng serve command

I'm encountering some troublesome errors while attempting to run my angular application. Honestly, I can't figure out what's wrong, so I'm hoping someone here can assist me. I didn't make any significant changes, just added a singl ...

Choosing Nested TypeScript Type Generics within an Array

I need help with extracting a specific subset of data from a GraphQL query response. type Maybe<T> = T | null ... export type DealFragmentFragment = { __typename: "Deal" } & Pick< Deal, "id" | "registeringStateEnum" | "status" | "offerS ...

Using a static value in the comparator is necessary for Array.find to function properly in Typescript

Looking to retrieve an item from an array: const device = this.selectedDevtype.devices.find(item => console.log(this.deviceID); return item.device_id === this.deviceID; }); console.log(device); When this.deviceID is logged, it shows "4", but t ...

Using Typescript to pass an optional parameter in a function

In my request function, I have the ability to accept a parameter for filtering, which is optional. An example of passing something to my function would be: myFunc({id: 123}) Within the function itself, I've implemented this constructor: const myFunc ...

Is there a way to adjust the width of the datepicker on my device?

I've been attempting to adjust the width of the date picker, but I'm having trouble achieving it. Below is my code: import React from "react"; import ReactDOM from "react-dom"; import { DatePicker, RangeDatePicker } from &qu ...

Remove a specific date entry from the database using VUE JS and Axios

I am encountering a challenge with Vuejs as I work on a To-Do list. The tasks need to be stored in a MySQL database, and I also want the ability to delete tasks. While I have succeeded in importing and creating data, I'm facing difficulty in deleting ...

Improving mongo information using angularjs

Have an Angular and MongoDB application. This is a part of my API where I have POST and PUT requests. The POST request works fine, but when I send a PUT request, I get an error "Cannot set property 'typelocal' of undefined". However, the PUT requ ...

Unveiling the Ultimate Method to Package Angular 2 Application using SystemJS and SystemJS-Builder

I'm currently in the process of developing an application and I am faced with a challenge of optimizing the performance of Angular 2 by improving the loading speed of all the scripts. However, I have encountered an error that is hindering my progress: ...

Encountering 404 errors when reloading routes on an Angular Azure static web app

After deploying my Angular app on Azure static web app, I encountered an error. Whenever I try to redirect to certain routes, it returns a 404 error. However, if I navigate from one route to another within the app, everything works fine. I have attempted t ...

Different ways to display a static content list using Vue's named slots

I'm struggling to make the following setup work: My parent template <comp> <a href="#" slot="links">link 1</a> <a href="#" slot="links">link 2</a> </comp> and in my comp ...

Tips for refreshing views with Angular JS

I am looking to refresh all the views displayed on my page. The layout consists of a Header, Footer, and Body view. Within the Header view, there is a dropdown menu where users can choose their preferred language. Upon selecting a language, I want all the ...

Having trouble displaying the selection menu when using Angular Strap?

//test.js const dropdownMenu = document.querySelector('.dropdown-menu'); dropdownMenu.addEventListener('click', (event) => { alert(`You clicked on ${event.target.textContent}`); }); // index.html <div class="dropdown"> ...

Click on a link to open it in the current tab with customized headers

In my Angular project, I am attempting to open a link by clicking a button that redirects to the specified URL using the following code: window.open(MY_LINK, "_self"); However, in this scenario, I also need to include an access token in the header when t ...

Add a unique CSS style to both text and image using anchor tags

Why isn't the hover effect of color transition and underline being applied to the image? It seems to only work for text. While I understand that the color transition may require a change in image color, shouldn't the underline still occur? This ...

Creating a PEG Grammar that can match either a space-separated or comma-separated list

I am currently working on creating a basic PEG (pegjs) grammar to analyze either a space separated list or a comma separated list of numbers. However, it seems like I am overlooking a crucial element in my implementation. Essentially, I aim to identify pat ...

What might be causing the component in Angular and TypeScript to have trouble reading the data returned by the service?

I've been working on this for hours without success. I created a web API get method that returns a simple array. public Hero[] getHeroes() { return new Hero[] { new Hero { Id = 1, Name = "Hunain Hafeez-1" }, ...

I used npm to install a package, but for some reason, it's not appearing in

When attempting to install jquery using npm, I entered the following command: npm install jquery However, upon opening the destination folder, it was empty. (The below text was copied from cmd) > C:\Users\mandar\Desktop\Mady> ...

Having trouble getting Vue create to work? If you're not seeing any output in the console or Vue UI,

I'm having trouble getting the Vue CLI to work. When I tried using vue create hello-world, it didn't return any output. I also attempted using vue ui, which showed ...

Accessing objects in an array in Vue 3 may pose a challenge

Struggling to access individual values from an Array fetched from Spring Boot in Vue. The issue is, I can only display the entire Array instead of looping through and showing single attributes from 0 to 3 per item like I did with the user object. The erro ...

Avoiding conflicts between banners, text, and images for HTML/CSS design

I'm having an issue with the banner I created for my project. It seems to be overlapping with text and images, hiding behind them. How can I fix this? Unfortunately, I can't post the link to my project here due to other files present. The specif ...