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>