skip to Main Content

so i have a Toolbar Item 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="$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>

that is a child for Toolbar:

<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 know i can use v-for...
    and then i use the Toolbar

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

ToolbarItem -> Toolbar -> EditorCompontn

how can i use emits here if the Toolbar Item compnent is a child for Toolbar that is a child for a component where is is used? For every item there is a diffrent function..

I think I can use the global store, but is there any other option?

2

Answers


  1. I am not sure, how the data should flow, but for this kind of parent-child communication you are missing the "listener" part.

    Documentation: https://vuejs.org/guide/components/events.html

    As ToolbarItem emits event with name event (would suggest to change it to something more descriptive :)), try to add listener for it to the parent component with method, that should be called, when the event happens…

    e.g.

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

    If you just need parent-child communication, then emits and props are totally fine ways how to do it (and if you don’t mind to couple both components together), for anything more complex a state management is a better option. Probably Pinia would be the best at the current time…

    If it’s still not working, try to install Vue.js Devtools and check what is emmited and how…

    Login or Signup to reply.
  2. What you could do is emit and listen to an event using the root element of vue.
    This is only if you want to avoid making emits throughout all of your nested child components until you get to the parent one. Here is an example applied to your case:

    Child

    <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

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

    Otherwise a simple chained emit will do just fine

    ToolbarItem

    <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>
    

    EditorCompontn

    <TipTapToolbar @event='callMyFunction'></TipTapToolbar>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search