0
votes

I'm trying to create an auto dropdown to have a list of categories. I'm using autocomplete-vue to create it.

The error I'm getting is

[Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'length' of undefined"

and

TypeError: Cannot read property 'length' of undefined

I'm not sure how to fix it even though my categories is being loaded and I can get a list of my categories when I type in the autocomplete, but I'm getting the above errors in my console so I don't see how I would be getting these errors.

Here is my code

My products.js

  Vue.component('product-app', require('./ProductApp.vue').default);
  Vue.component('product-create', require('./ProductCreate.vue').default);

  if (document.getElementById('product-app')) {
    const app = new Vue({
      el: "#product-app",
      data(){
        return{
          categories: []
        }
      },
      mounted() {
        axios.get('/categories').then(response => {
          this.categories = response.data;
        })
      }
    });
  }

My products.blade.php

  <div id="product-app">
    <product-app :categories="categories"></product-app>
  </div>

my ProductApp.vue

  <template>
    <div>
      <div class="row">
        <div class="col-md-6">
          <products :products="products"></products>
        </div>

        <div class="col-md-6">
          <product-create v-if="createProduct" :categories="categories"></product-create>
        </div>
      </div>
    </div>
  </template>

  <script>
    export default {
      props: ['categories'],
      data() {
        return {
          createProduct: false
        }
      },
      mounted() {
        this.bus.$on('create-product', payload => {
          this.createProduct = true;
        });
      }
    }
  </script>

My ProductCreate.vue

  <template>
    <div>
      <div class="row">
        <div class="col-lg-6">
          <div class="form-control">
            <label>Product Name</label>
            <input type="text" v-model="product.name" class="form-control">
          </div>

          <div class="form-control">
            <label>Product Description</label>
            <textarea v-model="product.description"></textarea>
          </div>

          <div class="form-control">
            <autocomplete-vue v-if="categoriesReady" :list="allCategories"></autocomplete-vue>
          </div>

          <button class="btn btn-success" @click="saveProduct">Save</button>
        </div>
      </div>
    </div>
  </template>

  <script>
    import AutocompleteVue from 'autocomplete-vue';

    export default {
      props: ['categories'],
      components: {
        AutocompleteVue
      },
      data(){
        return{
          categoriesReady: false,
          allCategories: [],
          product: {
            name: '',
            description: ''
          }
        }
      },
      methods: {
        getAllCategories(){
          for(let i = 0; i < this.categories.length; i++){
            let name = this.categories[i].name;
            this.allCategories.push({name: name});
          }

          this.categoriesReady = true;
        }
      },
      mounted(){
        this.getAllCategories();
      }
    }
  </script>
3

3 Answers

0
votes

I only got that error message when I did not pass the value of 'categories' for this component from the parent. 'undefined' object is 'this.categories' in 'for(let i = 0; i < this.categories.length; i++)'. when I pass a simple list, no error message, console is clear. please check it again

0
votes

I've solved my problem by moving

  axios.get('/categories').then(response => {
    this.categories = response.data;
  })

from my product.js

to my ProductCreate.vue, so my mounted section looks like this

  mounted(){
    axios.get('/categories').then(response => {
      for(let i = 0; i < response.data.categories.length; i++){
            let name = this.categories[i].name;
            this.allCategories.push({name: name});
          }

          this.categoriesReady = true;
    })
  }

after doing this my autocomplete-vue is working properly and I'm not getting any errors in my console.

Before marking this as answered I was wondering if you guys could tell me if this is best practice.

0
votes

Check your final mounted function.

Property length is undefined because category is not returned from the axios GET request yet before your loop tried to run it. Try making the request a promise by simply using async around and awaiting the request with await ( or any other way you prefer to resolve a promise). Then categories will be loaded before the loop runs. This should solve the problem.