0

I am creating blog commenting system, I want to show comments for a post using vue.js. In console, it says

Property or method "comment" is not defined on the instance but referenced during render.

Also, when I try to catch user name, I got this error

Error in render: "TypeError: Cannot read property 'user' of undefined"

I want to show comments and users who commented to a particular post

in show.blade.php.

web.php

Route::get('results/{post}', 'ResultsController@show')->name('posts.show');

ResultsController

public function show(Post $post)
{
    $recommended_posts = Post::latest()
                        ->whereDate('date','>',date('Y-m-d'))
                        ->where('category_id','=',$post->category_id)
                        ->where('id','!=',$post->id)
                        ->limit(7)
                        ->get();

    $posts['particular_post'] = $post;
    $posts['recommended_posts'] = $recommended_posts;

    //return $post->comments()->paginate(5);  it returns objects

    return view('posts.show',compact('posts'));
}

Comments.vue

<div class="reply-comment" :v-for="comment in comments">
                 <div class="user-comment" >
                    <div class="user">
                        <!--<img src="" alt="" >-->
                        <avatar :username="comment.user.name" :size="30" ></avatar>
                    </div>
                    <div class="user-name">
                        <span class="comment-name">{{ comment.user.name }}</span>
                        <p> {{ comment.body }} </p>
                    </div>
                </div>
                <div class="reply">
                    <div class="seemorecomments">
                        <a href="">see more</a>
                    </div>
                    <button class="reply-button">
                        <i class="fas fa-reply"></i>
                    </button>
                </div>
            </div>


<script>
import Avatar from 'vue-avatar'
export default {
    props: ['post'],
    components: {
        Avatar
    },
    mounted() {
        this.fetchComments()
    },
    data: () => ({
        comments: {
            data: []
        }
    }),
    methods: {
        fetchComments() {
            axios.get(`/results/${this.post.id}`).then(({ data }) => {
                this.comments = data
            })
        }
    }
}

show.blade.php

<comments-component :post="{{ $posts['particular_post']->comments }}"></comments-component>

migration table

Schema::create('comments', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->integer('user_id');
        $table->integer('post_id');
        $table->text('body');
        $table->integer('comment_id')->nullable();
        $table->timestamps();
    });

comment.php, I have this.

protected $with = ['user'];
6
  • Have you tried checking if your ResultsController@show returns the desired data? Commented Oct 3, 2019 at 6:34
  • I did, I put return $post->comments()->paginate(5); in controller, then I could see 5 objects. Commented Oct 3, 2019 at 6:38
  • console.log the data object in your api callback and check the data object. I think it would be this.comments = data.data. (check first your data object ) Commented Oct 3, 2019 at 6:42
  • you're using the same endpoint to show the view and getting the comments. So when the fetchComment() method is called, your ResultsController@show is not returning a JSON but rather a HTML consisting your view. Try creating a dedicated endpoint that returns the comments for a certain post in JSON format. Commented Oct 3, 2019 at 6:42
  • @JulioMotol I added a new endpoint Route::get('results/{post}/comments', 'CommentsController@index'); and changed like this (/results/${this.post.id}/comments) but it didn't work. Commented Oct 3, 2019 at 10:13

1 Answer 1

1

You have a couple of minor issues with your Vue file that can be addressed pretty quickly.

First, you should define comments as an empty array — a collection will be returned as an array of objects to the Vue. By adding an unnecessary data property in the beginning, you are allowing the v-for loop to run in your template before the data has been retrieved.

EDIT: I'm not sure about the way you wrote this data function, so I have re-written it a way in which I'm familiar.

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

Second, you want to get the correct data from the response. Axios data is stored another level deep (response.data). Of course, if you are paginating the results, they are one more level deep (response.data.data).

fetchComments() {
    axios.get(`/results/${this.post.id}`).then(response => {
        this.comments = response.data

        // or for paginated results
        // this.comments = response.data.data
    })
}

EDIT: Thank you for providing the Gist! I think I'm seeing things more clearly now.

Update your controller like so:
You want to load the comments into the post here.

public function show(Post $post)
{
    $recommended_posts = Post::latest()
                        ->whereDate('date','>',date('Y-m-d'))
                        ->where('category_id','=',$post->category_id)
                        ->where('id','!=',$post->id)
                        ->limit(7)
                        ->get();

    // load the post comments here
    $post->load('comments');
    $posts['particular_post'] = $post;
    $posts['recommended_posts'] = $recommended_posts;

    return view('posts.show',compact('posts'));
}

And you blade like so:
Your module wants a single post, not an array of comments.

<comments-component :post="{{ $posts['particular_post'] }}"></comments-component>

And you Vue like so:
You don't actually need to use Axios at all since we've already loaded the comments.

<script>
    import Avatar from 'vue-avatar'
    export default {
        props: ['post'],
        components: {
            Avatar
        },
        data() {
            return {
                comments: this.post.comments
            }
        },      
    }
</script>
Sign up to request clarification or add additional context in comments.

13 Comments

Thank you, but still I have a same error. "comment" is not defined on the instance" .
I have put $post->comments()->with('user')->get(); in ResultsController but still, I have the same error. Cannot read property 'user' of undefined".
I see you have newly added protected $with = ['user'] which should take care of the relation. Are you sure all of your comments are assigned to a user? Can you post your updated code to a Gist including the Comment.php model?
Thank you for answering me. I uploaded my codes, if you need more, feel free to ask. gist.github.com/YoheiUmezu/6583a87933ed94ff7df28eb532819632
I have also tried adding a new endpoint . I am glad if you check stackoverflow.com/questions/58217427/… .
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.