Home > Back-end >  Can't get parent element to receive data from child element in Vue.js
Can't get parent element to receive data from child element in Vue.js

Time:08-04

I have been trying to figure out this issue for about 4 hours at this point. I have watched at least a dozen youtube videos, read documentation, and pretty much exhausted every option before asking here. This application is built with Microsoft SQL Server, Vue.js, and C#. Database connectivity is working, as the getMotionPictures() method works correctly as does the deleteMotionPicture() method. I am honestly lost and frustrated at this point.

I am trying to create a child modal that emits an event with an object associated to pass to the parent element. The goal is to get the motionPicture object over to the parent so I can then use it on the createNewMotionPicture() function to push it to the database. It seems that the parent is capturing the event, because on line 26 of the parent <form-modal :getMotionPictureData="getMotionPictureData" v-show="showModal" @submit-modal="showModal = false; this.getMotionPictureData" /> the showModal does get set to false and the modal closes but from there the alert never happens. Here is my current code: (I apologize if this code is messy, I am new to Vue and trying my best)

Parent

<template>
  <div >
    <h1>Motion Picture Application</h1>
   <table class = "motionPictureTable">
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Release Year</th>
      <th>Actions</th>
    </tr>
    <tr v-for="data in result" :key="data.id">
    <td>{{data.name}}</td>
    <td>{{data.description}}</td>
    <td>{{data.releaseYear}}</td>
    <table>
      <tr>
        <img  src="@/assets/editIcon.png"/>
        <img  src="@/assets/copyIcon.png"/>
        <img v-on:click="deleteMotionPicture(data)"  src="@/assets/deleteIcon.png"/>
      </tr>
    </table>
    </tr>
   </table>
 
   <button v-on:click="showModal=true">Create</button>
    <form-modal v-show="showModal" @submit-modal="showModal = false; this.getMotionPictureData" />

  </div>
</template>

<script>
import FormModal from '@/components/FormModal.vue';

export default {

  components: {
    FormModal,
},

  mounted() {
    this.getMotionPictures();
  },

  updated() {
    this.getMotionPictures();
  },

  name: 'motion-pictures',

  data() {
    return {
    result: "",
    showModal: false,
    }
  },
  methods: {
    getMotionPictures() {
      fetch("https://localhost:44378/api/MotionPicture", {
        "method": "GET"
      }).then(response => {
        if(response.ok) {
          return response.json();
        }
      }).then(response => {
        this.result = response;
      })
    },

    deleteMotionPicture(data) {
      fetch(`https://localhost:44378/api/MotionPicture/${data.id}`, {
        method: "DELETE"
      }).then(() => alert(`record ${data.name} has been deleted`))
    }
  },

  getMotionPictureData(value) {
    console.log(value)
  },

  createNewMotionPicture() {
    fetch("https://localhost:44378/api/MotionPicture", {
      "method": "POST",
      "body": JSON.stringify(this.motionPicture)
      }).then(response => {
        if(response.ok) {
          return response.json();
        }
      }).then(() => alert(`record ${this.motionPicture.name} has been saved`))
    },


}

Child

<template>
  <div >
    <div >
      <h6>Please provide the following details:</h6>
      <form>
        <label for="name">Motion Picture Name</label><br />
        <input type="text" id="nameField" name="name" placeholder="Example: Good Fellas" v-model="this.motionPicture.name" />

        <label for="description">Description</label><br />
        <input type="text" id="descriptionField" name="description" placeholder="Optional" v-model="this.motionPicture.description" />

        <label for="releaseYear">Release Year</label><br />
        <input type="text" id="releaseYearField" name="releaseYear" placeholder="Example: 1996" v-model="this.motionPicture.releaseYear" />
      </form>
      <button type="submit" v-on:click="submitModal(); getMotionPictureData(this.motionPicture)">Submit</button>
      <button>Cancel</button>
    </div>
    <div >
    </div>
  </div>
</template>

<script>

  export default {
    name: "form-modal",

    data() {
        return {
            motionPicture: {
                name: "",
                description: "",
                releaseYear: "",
            }
        }
    },

    methods: {
        submitModal() {
            this.$emit('submit-modal', this.motionPicture);
        }
    },

props: {
  getMotionPictureData: Function
}

}

additionally, the logs are giving me this:

runtime-core.esm-bundler.js?d2dd:38 [Vue warn]: Unhandled error during execution of component event handler 
  at <FormModal onSubmitModal=fn > 
  at <MotionPictures> 
  at <App>
warn @ runtime-core.esm-bundler.js?d2dd:38
logError @ runtime-core.esm-bundler.js?d2dd:212
handleError @ runtime-core.esm-bundler.js?d2dd:204
callWithErrorHandling @ runtime-core.esm-bundler.js?d2dd:158
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?d2dd:164
emit$1 @ runtime-core.esm-bundler.js?d2dd:721
submitModal @ FormModal.vue?5e8e:40
onClick._cache.<computed>._cache.<computed> @ FormModal.vue?5e8e:15
callWithErrorHandling @ runtime-core.esm-bundler.js?d2dd:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?d2dd:164
invoker @ runtime-dom.esm-bundler.js?2725:369
runtime-core.esm-bundler.js?d2dd:38 [Vue warn]: Unhandled error during execution of native event handler 
  at <FormModal onSubmitModal=fn > 
  at <MotionPictures> 
  at <App>
warn @ runtime-core.esm-bundler.js?d2dd:38
logError @ runtime-core.esm-bundler.js?d2dd:212
handleError @ runtime-core.esm-bundler.js?d2dd:204
callWithErrorHandling @ runtime-core.esm-bundler.js?d2dd:158
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?d2dd:164
invoker @ runtime-dom.esm-bundler.js?2725:369
runtime-core.esm-bundler.js?d2dd:218 Uncaught TypeError: this.getMotionPictureData is not a function
    at onSubmitModal._cache.<computed>._cache.<computed> (MotionPictures.vue?645d:26:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:164:1)
    at emit$1 (runtime-core.esm-bundler.js?d2dd:721:1)
    at Proxy.submitModal (FormModal.vue?5e8e:40:1)
    at onClick._cache.<computed>._cache.<computed> (FormModal.vue?5e8e:15:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:164:1)
    at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js?2725:369:1)
onSubmitModal._cache.<computed>._cache.<computed> @ MotionPictures.vue?645d:26
callWithErrorHandling @ runtime-core.esm-bundler.js?d2dd:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?d2dd:164
emit$1 @ runtime-core.esm-bundler.js?d2dd:721
submitModal @ FormModal.vue?5e8e:40
onClick._cache.<computed>._cache.<computed> @ FormModal.vue?5e8e:15
callWithErrorHandling @ runtime-core.esm-bundler.js?d2dd:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?d2dd:164
invoker @ runtime-dom.esm-bundler.js?2725:369

CodePudding user response:

IMHO, the emitting and catching are good in the above code. One thing I see in the Parent component, you are referencing this in the event handler.

<form-modal v-show="showModal" @submit-modal="showModal = false; this.getMotionPictureData" />

We cannot use this inside the template, so that may be the culprit here. Handle the event using a function. It looks neat and less error-prone.

<form-modal v-show="showModal" @submit-modal="performAction" />

And register the method in your scripts section as:

{
  methods: {
    performAction(e) {
      // check "e" for the event args.
      this.showModal = false;
      this.getMotionPictureData()
    }
  }
}

CodePudding user response:

So I figured out my problem. For some reason when I was making methods, getMotionPictureData was actually NOT included in the methods: section, so thus it was never being called. All is well and working now

  • Related