I’ve got a problem where I want a child component to call a function given to it as a prop from the parent. I have done it before with other components, but with this it just doesn’t work.
Here are the relevant parts of my parent component:
<template>
<DataTable
:on-double-click="goToDevicePage"
/>
</template>
And here are the relevant parts of my child component:
<template>
<TableRow
v-for="(row, index) in filteredRows"
:key="row.id"
@dblclick="() => handleDoubleClick(row)"
/>
</template>
<script setup lang="ts">
const props = defineProps<{
onDoubleClick?: (cells: any[]) => void;
}>();
function handleDoubleClick(row: any) {
const cells = row.getVisibleCells();
if (props.onDoubleClick !== undefined) {
props.onDoubleClick(cells);
console.log("onDoubleClick is defined and called with cells:", cells);
} else {
console.log("onDoubleClick is undefined");
}
}
</script>
This always logs that the function is undefined and I’m not sure why.
I have tried making the function in the parent component to an arrow function like so:
:on-double-click="(cells: any[]) => goToDevicePage(cells)"
I have also tried things like setting the prop to required in the child component and typescript gives me no error, but it still logs that its undefined and if I remove the check, it just throws an error. I also tried some things like adding .prop to the parent component prop and removing the ‘on’ in the name of the prop because chatgpt said vue may be thinking it’s an event listener, but literally nothing works.
2
Answers
The problem is that, in Vue, property names are automatically
camelCased
, so:on-double-click
in the parent component is passed asonDoubleClick
to the child. In Vue’s template syntax, though,on-
prefixed properties are treated as event listeners, not as regular properties, hence it’s not passed down to the child component as you’ve expected.To fix this, change the following in the parent component: Change
:on-double-click="goToDevicePage"
to:onDoubleClick="goToDevicePage"
, in order to avoid the event-listener interpretation. By renamingon-double-click
toonDoubleClick
in the parent, Vue will pass it as a standard property instead of treating it as an event.The issue you’re encountering is because Vue interprets any prop name starting with "on" as an event listener, which Vue treats differently than a standard prop. When you name your prop onDoubleClick, Vue assumes it’s an event listener and does not pass it as a regular prop, which is why it appears undefined in the child component.
Solution
To avoid this issue, rename the prop to something that doesn’t start with "on" (e.g., doubleClickHandler or handleDoubleClick). Here’s how you can modify your code:
Parent Component
Child Component
Explanation
Renamed Prop: Changing onDoubleClick to doubleClickHandler prevents Vue from interpreting it as an event listener. Vue will now pass it as a standard prop.
Access the Prop Normally: In the child component, you can now use props.doubleClickHandler as expected without Vue interfering.
Additional Tips
If you need a naming convention for props that trigger actions, using names like onDoubleClickCallback or handleDoubleClick can also help avoid issues.
This should fix the problem, and you’ll see your callback function defined in the child component as expected!