I have a function to add a comment to a post. Now when you add a new comment to a blog the page needs to reload so that you can see the new added blog.
I now use location.reload()
but this refreshes the whole page which I don’t want to happen. How can I make it so that I only refresh the post?
I found this.$forceUpdate()
but this won’t reload the component at all.
Here are the files I use and how I do it right now, I removed the unnecessary code for If youre wondering why somethings are missing.
my container view:
<template>
<main>
<div class="container">
<MainContainerItem v-for="blog in blogs" :blog="blog"/>
</div>
</main>
</template>
<script setup>
import MainContainerItem from './MainContainerItem.vue';
import axios from 'axios'
</script>
<script>
export default {
name: "MainContainer",
data(){
return {
'blogs': null,
}
},
methods: {
getAllBlogs(){
axios.get('/api/blog')
.then((response) => {
this.blogs = response.data.blogs
console.log(this.blogs)
})
.catch((error) => {
console.warn(error)
})
},
},
mounted(){
this.getAllBlogs()
}
}
</script>
my other view:
<template>
<div class="blog__comments">
<div class="blog__comments__existingComment">
<div v-if="blog.comment !== null">
<div v-for="comments in blog.comments">
<span class="blog__comments blog__comments__existingComment--text">{{comments.comment}}</span>
</div>
</div>
</div>
<div class="blog__comments__add">
<img class="blog__comments blog__comments--profilePicture" :src="defaultProfilePicture">
<input class="blog__comments blog__comments--text" type="text" v-model="comment" placeholder="Write comment...">
<button @click="addComment()">Add comment</button>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: "MainContainerItem",
methods: {
/* add a comment to a blog */
addComment() {
axios.post('/api/blog/posts/' + this.posts_id + '/comment', {
'comment': this.comment,
'user_id': this.user_id,
'posts_id': this.posts_id
})
/* reload the page */
.then((response) => {
console.log(response)
/* my attempt with this.$forceUpdate() */
/* this.$forceUpdate(); */
/* with location.reload() how I have it now*/
location.reload();
this.blog.id = response.data.id
})
.catch(function (error) {
console.log(error);
});
},
}
}
</script>
my function to get the posts + comments:
public function getAllBlogs() : JsonResponse
{
return response()->json([
'blogs' =>
Posts::with(['comments' => function ($query) {
$query->with('user');
}])
->get()
]);
}
3
Answers
The trick is to not reload anything yourself, but update the data and have Vue figure it out through reactivity.
I think in your case, you can just add the new comment to the blog:
It is usually good practice to have your service return the comment data after saving, so you get the same data you would get when loading it (i.e. with IDs and other data added on server side). Then you can do something like:
Alternatively, you could emit the created value to the parent component that manages the data or put it all into a store.
Does that make sense? Does it work for you?
Do you really need to reload this page? Maybe you should just push newly added comment to this comments array you are iterating through?
You can’t modify props, so you should first move data from
prop
todata
variable inmounted
hook. Here is howMainContainerItem
should look like:You just need to change
location.reload()
tothis.$emit("refresh")
.Then, change this code to: