Search code examples
javascriptvue.jsvuejs3vue-componentvuetify.js

Vue.js- I am getting "this.cancelOrderFunction is not a function" error while calling method inside a child component


I am trying to trigger a method which changes the text content of currentStatus variable, when a button (Confirm Cancel) is clicked. This button is present in the child component inside a dialog box whereas the method should be in the parent component. So I am trying to pass this method as props to child component. After writing the code as below, I am getting the error, "this.cancelOrderFunction is not a function" in the console. I am aware that this is a minute error, but unable to find it. I have tried solving this error with the below code.

changeStatus.vue (Parent Component)

<template>
    <cancelOrder :cancelOrderFunction="cancelOrderFunction"></cancelOrder>
</template>

<script>
import cancelOrder from "../components/cancelOrder.vue"; /*importing child component*/
export default {
  data: () => ({
    currentStatus: "ACTIVE",
  }),
  methods: {
    cancelOrderFunction() {
      this.currentStatus = "CANCELLED";
    },
  },
  components: {
    cancelOrder,
  },
};
</script>

cancelOrder.vue (Child Component)

<template>
    <v-btn @click="confirmCancelOrder">Confirm Cancel</v-btn>
</template>

<script>
export default {
  props: ["cancelOrderFunction"],
  methods: {
    confirmCancelOrder() {
      this.cancelOrderFunction();
    },
  },
};
</script>

The cancelOrder.vue component consists of a button Cancel Order which further opens a dialog box. This dialog box consists of Confirm Cancel button which when clicked, the dialog box should close and the cancelOrderFunction should be triggered simultaneously. In my case, the dialog box is being closed consistently, but the method is not being called due the mentioned error.


Solution

  • Variables can only be passed to children. If you want to call a function from a child that is in a parent you should use "emit".

    https://vuejs.org/guide/components/events.html#emitting-and-listening-to-events

    It's also a good idea to bind this as a v-model. Because it binds both value and emitted values into one. It all depends on the case.

    Below is the solution how you should do it using emit. Let me know if that's exactly what you meant.

    changeStatus.vue (Parent Component)

    <template>        
            <cancelOrder @cancel-order-function="cancelOrderFunction"></cancelOrder>
    </template>
    <script>
    ...
    methods: {
        cancelOrderFunction(data) {
        //do whatever you want with data
        }
    }
    ...
    </script>
    

    cancelOrder.vue (Child Component)

    <template>
        <v-btn @click="confirmCancelOrder">Confirm Cancel</v-btn>
    </template>
    
    <script>
    export default {
      emits: ["cancel-order-function"],
      methods: {
        cancelOrderFunction() {
          this.$emit('cancel-order-function', data)
        },
      },
    };
    </script>