Managing Emitted Events in Vue.js Components within Components: A Guide

I have created a Toolbar Item component as follows:

<template>
  <div
    class="flex cursor-pointer items-center justify-center rounded-full border-2 border-gray-300 p-1 shadow-sm transition-all duration-300 hover:scale-110 hover:bg-black hover:text-white"
    @click="$emit('event')"
    :class="isActive ? 'bg-black text-white' : ''"
  >
    <Icon @click="setActive()" :icon="icon" />
  </div>
</template>
<script setup>
import { Icon } from '@iconify/vue'
import { defineProps, defineEmits } from 'vue'
import { ref } from 'vue'
const props = defineProps({
  icon: String
})
const emits = defineEmits({
  event: String
})
const isActive = ref(false)
function setActive() {
  isActive.value = !isActive.value
  console.log(isActive.value)
}
</script>

<style scoped></style>

This component is nested inside a Toolbar parent component:

<template>
  <div class="flex gap-2 rounded-3xl border-2 border-gray-300 p-2 shadow-md">
    <TipTapToolbarItem icon="ooui:bold-b"></TipTapToolbarItem>
    <TipTapToolbarItem icon="clarity:italic-line"></TipTapToolbarItem>
    <TipTapToolbarItem icon="fa-solid:strikethrough"></TipTapToolbarItem>
    <TipTapToolbarItem icon="mingcute:heading-1-fill"></TipTapToolbarItem>
    <TipTapToolbarItem icon="mingcute:code-fill"></TipTapToolbarItem>
    <TipTapToolbarItem icon="tabler:blockquote"></TipTapToolbarItem>
    <TipTapToolbarItem icon="octicon:horizontal-rule-16"></TipTapToolbarItem>
  </div>
</template>
<script setup>
import TipTapToolbarItem from './TipTapToolbarItem.vue'
</script>

<style scoped></style>

    I am aware that v-for can be used...
    and then the Toolbar is utilized

<template>
  <TipTapToolbar></TipTapToolbar>
  <editor-content class="h-[200px] w-[200px] bg-blue-500" placeholder="tiptap" :editor="editor" />
</template>

The hierarchy is as follows: ToolbarItem -> Toolbar -> EditorCompontn

I am wondering how to handle emits in this structure where the Toolbar Item component is a child of Toolbar which in turn is a child of a component where it is implemented. Each item requires a different function...

I am considering using the global store, but are there any other alternatives?

Answer №1

Uncertain about the flow of data, but it seems like you are missing the "listener" part in this parent-child communication.

For more information, check out the documentation: https://vuejs.org/guide/components/events.html

When ToolbarItem emits an event with the name event (consider changing it to something more descriptive), make sure to add a listener for it in the parent component and specify the method to be executed when the event occurs...

For example:

<TipTapToolbarItem
  icon="ooui:bold-b"
  @event="someMethod()"
/>

If simple parent-child communication is all that's needed, then using emits and props is sufficient (unless you're okay with tightly coupling both components together). However, for more complex scenarios, consider using a state management solution like probably Pinia at this time...

If the issue persists, try installing Vue.js Devtools to inspect what events are being emitted and how they are being handled...

Answer №2

If you want to streamline event handling in Vue, consider emitting and listening to events using the root element. This approach can help avoid emitting events through nested child components until they reach the parent component. Here's an example tailored to your scenario:

Child Component

<template>
  <div
    class="flex cursor-pointer items-center justify-center rounded-full border-2 border-gray-300 p-1 shadow-sm transition-all duration-300 hover:scale-110 hover:bg-black hover:text-white"
    @click="$root.$emit('event')"
    :class="isActive ? 'bg-black text-white' : ''"
  >
    <Icon @click="setActive()" :icon="icon" />
  </div>
</template>

Top Level Parent Component

<script>
export default {
  mounted() {
    this.$root.$on('event', (name) => {
      // Perform actions here...
    })
  }
}
</script>

Alternatively, you can use a simple chained emit for straightforward event propagation.

Toolbar Item

<div
    class="flex cursor-pointer items-center justify-center rounded-full border-2 border-gray-300 p-1 shadow-sm transition-all duration-300 hover:scale-110 hover:bg-black hover:text-white"
    @click="$emit('event')"
    :class="isActive ? 'bg-black text-white' : ''"
  >
    <Icon @click="setActive()" :icon="icon" />
  </div>

TipTapToolbar

<TipTapToolbarItem icon="ooui:bold-b" @event='$emit('event')></TipTapToolbarItem>

EditorComponent

<TipTapToolbar @event='callMyFunction'></TipTapToolbar>

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

Arranging an array of JSON objects without keys in a specific order

Here is an array containing multiple objects without any keys: const result = [ ["Joe", "1", "2.22%", "$3,000.00"], ["Tom", "1", "2.22%", "$4,650.00"], ["Ryan", "4", "4.44%", "$18,925.00"], ["Jordan", "2", "4.44%", "$3,300.00"], ["Fred", "0" ...

Creating dynamic images in JavaScript by assigning URL paths from string variables

Currently, I am utilizing JavaScript to parse through an XML file. One interesting aspect of the XML is that it contains URLs which link to images like this one: http://localhost/pic.jpg Throughout the parsing process, I am storing each URL as a string va ...

How can I submit multiple dropdown menus when they are changed?

I recently added Four dropdown menus on my index.php page. <select name="filter_month" class="filters"> <option>Select a Month</option> <option value="1">January</option> <option value="2">February</optio ...

What is the process for selecting the Node version when installing with .nvm?

I am having an issue with nvm in the terminal. When I try to run npm install <something>, it always installs the package in node version 9.4.0, regardless of the version set using nvm. Even after switching to node version 10.15.3 using nvm use v10.1 ...

Using Typescript to change a JSON array of objects into a string array

I'm currently working with the latest version of Angular 2. My goal is to take a JSON array like this: jsonObject = [ {"name": "Bill Gates"}, {"name": "Max Payne"}, {"name": "Trump"}, {"name": "Obama"} ]; and convert it into a st ...

Import ES6 code by wrapping it in parentheses

Currently delving into React Native and I'm intrigued by the parentheses used in the first line of import. import React, { Component } from 'react'; import { AppRegistry, Text } from 'react-native'; class HelloWorldApp extends Co ...

How to apply styling to a specific portion of text within a list element using Vue.js

Despite my best efforts, I am struggling to style only the word "healthy" within the 'It is healthy!' string using computed properties, watchers, and methods in vuejs. I'm at a loss for how to achieve this unique styling. <template> ...

Preventing circular dependencies while upholding the structure of modules in Express

I am developing an express app in ES6 and organizing my files by functionality. In this structure, each module has an index.js file that is responsible for exporting relevant methods, classes, etc. Other modules simply require the index.js from another mod ...

Trigger an event within a linked component

I've been working on a connected component where I'm attempting to dispatch the clear action from. Here's a snippet of the code: import {createElement} from 'react'; import reduce from 'lodash/fp/reduce'; import {connect ...

Looking to duplicate a row of input fields while maintaining the same validation rules as the original row?

form <form action="assign_web_menu_action.php" method="post" name="form1" id="form1" > <table id='menuAssign'> <tbody> <tr class="clone_row"> <td> <input type="text" name="menuname[]" id="menuname1" ...

Encountering a 500 error when making API requests after deploying Next.js on Vercel, although they work fine

I recently deployed my Next.js app to Vercel, and I'm experiencing issues with my API calls returning a 500 status code, even though they work perfectly fine on localhost. The initial load using getStaticProps seems to be working, so I suspect the con ...

JavaScript: Incorporating an operator into a specific object (instead of the entire class)

Are you familiar with how to include an operator in an object (rather than the entire class)? When it comes to a method, I know you can achieve that by: my_object.new_function = function(){return 1}; Then invoking my_object.new_function() will output ...

JavaScript ACTING UP -> CROSS-ORIGIN RESOURCE ACCESS ERROR

After extensive research and troubleshooting, it dawned on me that the issue was not with JavaScript itself. Instead, I was facing a cross origin resource exception, which occurred because the ajax request was unable to access my server script due to lac ...

What are some methods for singling out a specific table row?

When working on my app, I faced the task of importing a JSON file and displaying its contents in a table with 3 columns. However, there are two main issues that arose: Utilizing array index for the row key is not recommended due to the table also having ...

What is the correct method for properly disposing of a Three.js Scene in version r55?

It appears that Three.js lacks a proper method for disposing of a THREE.Scene and all its contents. My current approach is as follows: $.each(scene.__objects, function(idx, obj) { scene.remove(obj); ...

Strategies for extracting special character codes from API data within a React functional component

I have been experimenting with a simple trivia API to improve my understanding of REACT. I have noticed that the question data is returning with special character codes, which is causing issues with react jsx. Can anyone suggest a method to easily convert ...

Creating dynamic side navigation in VuePress is a simple process

Is there a way to automate the creation of my VuePress site's left side navigation without having to manually add entries? I've tried using the "vuepress-auto-sidebar" plugin, but it includes unwanted folders like .git and node_modules, and does ...

Creating a custom HTML5 canvas with images from a JSON array

I am currently working on a project to develop a unique slideshow feature by hosting images in an external JSON array and then loading them onto an HTML page. The next step is to insert these images onto an HTML5 canvas. While I have successfully loaded a ...

Eliminating the selected option from the dropdown menu after it has been added with Angular

HTML Code <!doctype html> <html ng-app="plunker"> <head> <meta charset="utf-8> <title>AngularJS Plunker</title> <link rel="stylesheet" href="style.css"> <script> document.write("<base href=&b ...

Tips for developing screen reader-friendly AJAX areas and managing updates to the DOM?

My interactive user process operates in the following manner: Users encounter a dropdown menu featuring a selection of cities. Upon picking a city, an AJAX request retrieves all buildings within that city and inserts them into a designated div (the AJAX ...