Home > Blockchain >  How to properly emit an event passed as a string parameter to emit() function?
How to properly emit an event passed as a string parameter to emit() function?

Time:08-31

What I'm trying to do is to pass the emit name as a string (e.g. 'showComponent') from child to parent, then evoke another emit in emitAction(callbackName: string), and eventually call the showComponent() function.

What am I doing wrong?

Parent component:

<script setup lang="ts">

const showLoginPopup: Ref<boolean> = ref(false);

function showComponent() {
  showLoginPopup.value = true;
}

const emit = defineEmits<{
  (event: string): void;
}>()


function emitAction(callbackName: string) {
  emit(callbackName);
}

</script>

<template>
<ActionVue @emitAction="emitAction" v-for="action in actions"
            :title="action.title"
            :description="action.description"
            :buttonTitle="action?.buttonTitle"
            :actionType="action.actionType" />
</template>

Child component:

<script setup lang="ts">
const props = defineProps<Action>();
const emit = defineEmits<{
  (event: 'emitAction', callbackName: string): void;
}>()

</script>

<template>
    <button @click="emit('emitAction', props.actionType)">
     {{  props.buttonTitle }}
    </button>
</template>

CodePudding user response:

A second emit isn't going to do anything except emit the event up to the parent's parent component. I would recommend simply running the function based on the emit name

child:

<button @click="emit('showComponent')"

parent:

<ActionVue @showComponent="showComponent()">

If you really want to call a function based on a string value, you can dynamically call the function stored on the current app instance:

Parent component:

<script setup lang="ts">
    import { getCurrentInstance } from 'vue'
    const app = getCurrentInstance()

    function emitAction(callbackName: string) {
          // if callbackName === 'showComponent', runs function showComponent()
          app.setupState[callbackName](); 
    }

    function showComponent() {
        showLoginPopup.value = true;
    }
}

CodePudding user response:

When calling emit within the template markup, it needs to be $emit(…). See my Codepen example, specifically how I'm calling emit in the child components.

<!-- works -->
<button @click="$emit('foo', 'bar')">Click</button>
<!-- does not work; "emit" is not a defined function for the component -->
<button @click="emit('foo', 'bar')">Click</button>
  • Related