12

I am using Laravel and vue-router.

<template>
    <div class="content__inner">
        <div class="forums">

            <!-- Heading -->
            <div class="forums__heading" :style="'border-bottom:2px solid #' + board.category.color">
                <div class="lg-8 md-8 sm-12 column column__first">
                    <h2 class="forums__heading__title">{{ board.title }}</h2>
                </div>
                <div class="lg-1 md-1 sm-1 dtop column text-center">
                    <strong>Replies</strong>
                </div>
                <div class="lg-3 md-3 sm-4 column text-right">
                    <strong>Latest Reply</strong>
                </div>
                <div class="clearfix"></div>
            </div>

            <!-- Content -->
            <div class="forums__content">
                {{ board.category }}
            </div>

        </div>
    </div>
</template>

<script>

    export default {

        data() {
            return {
                board: [],
            }
        },

        created() {
            this.fetch_board(this.$route.params.slug);
        },

        methods: {

            /**
             * Fetch the board.
             *
             * @param string slug   The slug for the board.
             */
            fetch_board(slug)
            {
                this.$http.get('/api/forums/board/' + slug).then((response) => {
                    this.board = response.data;
                });
            },

        }

    };

</script>

The 'fetch_board' function returns an object like the following:

board:Object {
    id:5,
    title:"Game Discussion",
    slug:"5-game-discussion",
    description:"General talk about the game.",
    restriction:null,
    category_id:2,
    category:Object {
        id:2
        title:"Community",
        color:"2ECC71",
        created_at:"2017-05-02 07:30:25",
        updated_at:"2017-05-02 07:30:25",
    }
    created_at:"2017-05-02 07:30:25",
    updated_at:"2017-05-02 07:30:25",
}

When I access the {{ board.category }} it displays the object correctly; but when I access {{ board.category.title }} it displays the title, but ALSO gives a TypeError.

Why I am getting this error if the data is being loaded correctly?

How can I avoid/fix this error?

8
  • 3
    Your template tries to access board.category or board.title before 'board' has these properties. Thats why you get these warnings. Either create a blank title inside board or use v-if wherever you are accessing something that does not exist initially. Commented May 2, 2017 at 12:18
  • Except that when I access board.category or board.title I don't get any error. I only get the error when trying to access board.category.title. Commented May 2, 2017 at 12:36
  • Yes. Thats really weird. jsfiddle.net/yMv7y/2571 You should open an issue may be. Commented May 2, 2017 at 12:47
  • 4
    Deepak, Imagine17, is not an issue, if board exists but board.category doesn't you don' get an error, is jsut undefined, the problem is when you try to access board.category.title, becuase category is not an object. You can do board.whatever and don't get error. Deepak answer is correct: <div class="forums__heading" v-if="board.id" for example, will work. Commented May 2, 2017 at 13:03
  • 2
    try to initialize your board as empty object instead of empty array Commented May 2, 2017 at 14:00

2 Answers 2

6

You are seeing this error because you are initializing "board" to an empty array. The component tries to evaluate "board.category.title" when it binds the reactivity just prior to the created() hook.

With board set as an empty array, step by step the evaluation might look like this:

const board = [];

const category = board.category; // undefined

const title = category.title; // TypeError, because category is undefined

You should stop seeing this error if you initialize your data like so:

data() {
  return {
    board: {
      category: {
        title: ''
      }
    }
  }
}

Here is the Vue lifecycle diagram which illustrates when the created() event is fired

Sign up to request clarification or add additional context in comments.

Comments

1

This error is explained in the official Vue documentation:

Since Vue doesn’t allow dynamically adding root-level reactive properties, you have to initialize Vue instances by declaring all root-level reactive data properties upfront, even with an empty value:

var vm = new Vue({
  data: {
    // declare message with an empty value
    message: ''
  },
  template: '<div>{{ message }}</div>'
})
// set `message` later
vm.message = 'Hello!'

If you don’t declare message in the data option, Vue will warn you that the render function is trying to access a property that doesn’t exist.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.