1
votes

I am a beginner in Vuejs, I'm trying to load this component but it's not working, first I get that course.pivot is undefined, the console.log on mounted() is not firing even If I tried to log just a string, I'm passing a prob from the view but it is not being rendered I think, I tried to replace course with a variable on data() e.g(greetings: 'hi there') and echo it out using {{ greetings }} in the template, I got an error that greetings was undefined, even after deleting some of the required functionality to get the component to load, when I press on the button I get that onSubmit is not defined on the instance as well, so If my code is right(which isn't probably the case), this means there's something else that I'm missing, I'm versioning these files using elixir and gulp, and they are loading properly in the browser, even the example component doesn't load properly, the mounted() method doesn't fire as well, not sure what's going on.

course-buttons.vue:

<template>
  <div>

    <button @click.prevent="onSubmit(course)" type="button" v-if="course.pivot.completed === 1" class="btn btn-sm" id="coursetrue"></button>

    <button @click.prevent="onSubmit(course)" type="button" v-if="course.pivot.completed === 0" class="btn btn-sm" id="coursefalse"></button>

  </div>
</template>

<script>
  export default {

    props: ['courseId'],

    mounted() {
      axios.get('/getCourse/' + this.courseId)
      .then((response) => {
        console.log(response)
        this.course = response.data.course
       // console.log('something')
      });
    },

    data: function () {
      return {
        course: ''
      }
    },
    methods: {
      onSubmit: function(course) {
        axios.post('/MyCourses/' + this.course.name)
        .then((resp) => {
          console.log(resp.data)
        });
     }
    }
  }
</script>

There's probably an error in the way my code is structured, because I don't know how to properly work with a prob.

Here is the courses.blade.php, the component is a part of a table inside a foreach loop:

<tbody>
    @foreach ($courses as $course)
      <tr>
        <td>{{ $course->name }}</td>
        <td>{{ $course->appointment }}</td>
        <td>{{ $course->room_id }}</td>
        <td>
           <form method="POST" action="{{ route('course.completed', $course->name) }}" id="form-submit">
               {{ csrf_field() }}

           <course-buttons :courseId="{{ $course->id }}"></course-buttons>

           </form>
       </td>
     </tr>
   @endforeach
</tbody>

Here I'm trying to pass the id of the course.

Here is app.js file:

require('./bootstrap');

Vue.component('example', require('./components/Example.vue'));

Vue.component('course-buttons', require('./components/course-buttons.vue'));

const app = new Vue({
   el: '#app',
});

When I inspect this in chrome using vuejs devtools, I get the instance of the component, but it doesn't show that anything was declared on the instance, no data and no props, which means there's an issue.

Here are the errors I'm getting:

1- [Vue warn]: Property or method "course" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in component )

2- [Vue warn]: Error when rendering component :

3- Uncaught TypeError: Cannot read property 'pivot' of undefined

What I want to do eventually is just having a button that changes colors depending on the status of the course, whether if it is completed or not, that's it.

2
"first I get that course.pivot is undefined" Well, yes. When your component is initialized, your data function is setting course's value to ''. course.pivot is indeed undefined at that point, so your template spits out the error. You're loading course.pivot later on. - ceejayoz
Either put the stuff that depends on course being set in a v-if="course" so it's not executed until the data comes back, or have the data function set dummy values for all its properties. - ceejayoz

2 Answers

1
votes

do you have a div with id="app" somewhere? Also, try running your mounted() code inside of the create() function lifecycle hook. Im not sure if vue will pick up on changes to your model if you initialize it your data in the mounted() method.

Also, you should define your course object with all the properties that it is going to have when it gets set by the network call

   return {
        course: {
             id: "", name: "", credits: "", etc.....
         }
      }

If you dont do it like this, vue will not be able to track changes to those properties

0
votes

It turns out that for some reason the generic example.vue file that comes with Laravel doesn't work as expected on my machine/environment, maybe I have something that isn't configured right, anyway the solution was easy:

  • Go to Vuejs single file component page.
  • In their template you'll find that instead of export default that is written in the script tag in the Laravel example file, VueJs has module.exports for their template, I swapped these in my files and everything worked.

I don't know how and I don't know why, unfortunately I lack the knowledge in that area, but at least the problem was solved.