Search code examples
javascriptvue.jsvuejs3vue-component

Function prop passed to component is undefined in Vue3


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.


Solution

  • 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

    <template>
     <DataTable
      :double-click-handler="goToDevicePage"
       />
    </template>
    

    Child Component

    <template>
      <DataTable
      :double-click-handler="goToDevicePage"
       />
    </template>
    

    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!