I am trying to build a like button on vuejs using axios.
I have a mongoDB controller that works perfectly on postman. But i can't make it work in the frontend.
I want to add the userId in the usersLiked array and i want to add 1 in the like counter on click. And if the user click on an already liked button, i want to take off his userID from the array and do 0 on the like counter.
thats my schema
const postSchema = mongoose.Schema({
userId: { type: String, required: true, ref: "User" },
content: { type: String, required: true, trim: true },
imageUrl: { type: String, trim: true },
likes: { type: Number, default: 0 },
usersLiked: [{ type: String, ref: "User" }],
firstname: {type: String, required: true, trim: true },
lastname: {type: String, required: true, trim: true },
created_at: { type: Date},
updated_at: { type: Date }
});
this is the axios function i tried
likePost() {
const thisPostId = localStorage.getItem("ThisPostId")
axios
.post('http://127.0.0.1:3000/api/post/like/' thisPostId, {
headers: {
Authorization: "Bearer " localStorage.getItem("token"),
},
})
.then((response) => {
console.log(response.data);
this.$set(this.post, 'usersLiked', this.post.usersLiked !== response?.data?._id)
})
.catch((error) => console.log(error));
}
},
the html
<div v-if="post.usersLiked == user._id">
<div >
<p >{{ post.likes }} like !</p>
<button v-on:click="likePost(post._id)" style="color: pink" type="submit"
title="Aimer ce post !" >
<font-awesome-icon icon="fa-solid fa-thumbs-up" /> Like !
</button>
</div>
</div>
<div v-else>
<div >
<p >{{ post.likes }} like !</p>
<button v-on:click="likePost(post._id)" type="submit" title="Aimer ce post !"
>
<font-awesome-icon icon="fa-solid fa-thumbs-up" /> Like !
</button>
</div>
</div>
and this is my data
data() {
return {
posts: [],
post: {
file: "",
content: "",
},
showModal: false,
showModifyPost: false,
user: {
firstname: "",
lastname: "",
_id: "",
},
};
},
CodePudding user response:
Adding a computed function to get the current user's like status can be helpful here.
{
computed: {
myLikeStatus() {
if (!this.user) return false
if (!Array.isArray(this.posts.usersLiked)) return false
return !!this.posts.usersLiked.find(item => item === this.user._id)
}
}
}
With this computed function you should be able to set classes on the like button to show already-liked
status.
<button @click="likePost" type="submit" title="Aimer ce post !"
:
>
<font-awesome-icon :icon="`fa-solid fa-thumbs-${myLikeStatus ? 'up' : 'down'}`" /> Like !
</button>
And now in the LikePost method, just assign the response data to the reactive posts
variable as:
{
methods: {
likePost() {
const thisPostId = localStorage.getItem("ThisPostId")
axios
.post('http://127.0.0.1:3000/api/post/like/' thisPostId, {
headers: {
Authorization: "Bearer " localStorage.getItem("token"),
},
})
.then((response) => {
console.log(response.data);
this.post = response.data
})
.catch((error) => console.log(error));
}
},
}
}
Also, your like count should be reactive the way it is now if the API is returning the correct count.