Vue.js cannot change data in other hook and methods - javascript

I'm developing vlog service with flask, vue.
Between two components of vue - PostList and PostDetail vue -, I use Eventbus to send postId. PostList send postId and PostDetail receive it. And then i request GET method to server using axios and postId. And i changed data like 'this.sth = result.data' but it doesn't changed
here is my code except css
postlist
<template>
<div class="list-container">
<div class="post-list" v-for="post in posts" v-bind:key="post.key" >
<img :src="`http://54.180.79.49/${post.image}`" class="post-img">
<div class="post-container" >
<div class="post-title" v-on:click="redirect(post.post_id)"><p class="text-title">{{ post.title }}</p></div>
<div class="content-container">
<p class="post-content">{{ post.content }}</p>
<div class="meta-container">
<p class="post-meta">{{ formatDate(post.creation_time) }}, {{ post.commentCount }}개</p>
<div class="heart-container">
<img src="../assets/heart.png" class="heart-img">
<p class="heart-cnt">0</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import moment from 'moment'
export default {
name: 'PostList',
data () {
return {
posts: [],
category: '',
isAll: false
}
},
created: function () {
this.$EventBus.$on('category', (category) => {
this.isAll = !this.isAll
this.category = category
if (this.isAll === false) {
this.$http.get('/post', {params: {category: 'All'}}).then((result) => {
this.posts = result.data
console.log(result.data)
}).catch(function (error) {
console.log(error)
})
} else {
console.log(this.category)
this.$http.get('/post', {params: {category: this.category}}).then((result) => {
this.posts = result.data
console.log(result.data)
}).catch(function (error) {
console.log(error)
})
}
})
this.$http.get('/post', {params: {category: 'All'}}).then((result) => {
this.posts = result.data
console.log(result.data)
}).catch(function (error) {
console.log(error)
})
},
methods: {
tmp: function () {
console.log(1)
},
formatDate: function (date) {
return moment(date, 'YYYY-MM-DD').format('YYYY-MM-DD')
},
redirect: function (id) {
this.$router.push('/detail')
this.$EventBus.$emit('post_id', id)
}
}
}
</script>
postdetail
<template>
<div class="body-wrapper">
<div class="profile-container">
<div class="profile-wrapper">
<img src="../assets/profile.png" class="small-profile">
<div class="intro-wrapper">
<p class="small-name">test</p>
<p class="small-intro">test</p>
</div>
</div>
</div>
<div class="all-wrapper">
<div class="title-container">
<div class="title-wrapper">
<div class="heart-wrapper">
<img src="../assets/heart.png" class="big-heart">
<div class="count">256</div>
</div>
<div class="title"><p>{{ this.info.title }}</p></div>
</div>
</div>
<div class="wrapper-wrapper">
<div class="meta-wrapper">
<div class="date"><p>{{ this.info.creation_time }}</p></div>
<div class="category"><p>{{ this.info.category }}</p></div>
</div>
</div>
<div class="detail-wrapper">
<div class="detail-body">
<!-- <img v-for="image in this.images" v-bind:key="image.key" :src="`http://54.180.79.49/${image}`" class="post-img"> -->
<div class="post-content"><p>{{ this.info.content }}</p></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'PostDetailBody',
data () {
return {
info: {}
}
},
created: function () {
console.log(this.id)
this.$EventBus.$on('post_id', (id) => {
this.$http.get('/post/' + id).then((result) => {
this.info = result.data
}).catch(function (error) {
console.log(error)
})
})
}
}

I saw the problem in here:
redirect: function (id) {
this.$router.push('/detail')
this.$EventBus.$emit('post_id', id)
}
and
created: function () {
console.log(this.id)
this.$EventBus.$on('post_id', (id) => {
this.$http.get('/post/' + id).then((result) => {
this.info = result.data
}).catch(function (error) {
console.log(error)
})
})
}
Basically, at the time you emit the event this.$EventBus.$emit('post_id', id), PostDetail component is not created yet. So it this.$EventBus.$on isn't registered.
One possible solution is embedded id in url, and read post's id from router params
redirect: function (id) {
this.$router.push('/detail/' + id)
}

Related

Toggle class(or change style) of element when element in clicked, Vuejs

The way i am getting data is little bit complicated. I have "tweets" array where data is stored and each tweet is a card where i successfully change style when card is clicked(markTweet function), but there are also replies for each tweet which are shown same as tweets(each reply has its own card). The way i am getting data from server:
let replies = []
for(const tweet of tweets) {
let reply = await SQL('SELECT * FROM tweet_replies WHERE tweet_replies.conversation_id = ?', tweet.tweet_id)
replies.push(reply)
}
const data = {
tweets: tweets,
page: parseInt(currentPage),
numberOfPages: arr,
replies
}
Then i have component in vue. You can see replies are stored in tweets array in each tweet as tweetReplies.
In markReply func, am succesfully adding id to array.
<template>
<div class="container-full">
<div class="tweets-container">
<div
v-for="(tweet, i) in tweets"
:key="tweet.id"
>
<div
class="tweet-card"
:class="{ selected: tweet.isSelected }"
#click="markTweet(tweet.tweet_id, i)"
>
<div class="text">
<p
v-html="tweet.tweet_text"
>
{{ tweet.tweet_text }}
</p>
</div>
</div>
<div class="replies">
<div
v-for="(reply, index) in tweet.tweetReplies"
:key="reply.tweet_id"
#click="markReply(reply.tweet_id, index)"
>
<div class="tweet-card tweet-reply">
<div class="text">
<p>
{{ reply.tweet_text }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import { getUserToken } from '#/auth/auth'
import moment from 'moment'
import { BFormTextarea, BButton, BFormSelect } from 'bootstrap-vue'
export default {
components: { BFormTextarea, BButton, BFormSelect },
data() {
return {
tweets: [],
tweetActionIds: [],
categories: [],
}
},
beforeMount() {
this.getTweets()
},
methods: {
getTweets() {
this.tweets = []
const API_URL = `${this.$server}/api/twitter/tweets`
const params = {
token: getUserToken(),
page: this.$route.query.page,
newCurrentPage: newCurrent,
}
axios.post(API_URL, null, { params }).then(res => {
this.currentPage = res.data.page
this.numberOfPages = res.data.numberOfPages
if (res.data) {
res.data.tweets.forEach(tweet => {
const tweetData = {
id: tweet.id,
tweet_id: tweet.tweet_id,
tweet_text: htmlText,
tweet_text_en: htmlTextEn,
twitter_name: tweet.twitter_name,
twitter_username: tweet.twitter_username,
added_at: moment(String(tweet.added_at)).format(
'MM/DD/YYYY hh:mm',
),
URL: tweet.URL,
isSelected: false,
tweetReplies: [],
}
this.tweets.push(tweetData)
})
res.data.replies.forEach(reply => {
reply.forEach(r => {
this.tweets.forEach(tweet => {
if (tweet.tweet_id === r.conversation_id) {
tweet.tweetReplies.push(r)
}
})
})
})
}
})
},
markTweet(tweetId, i) {
const idIndex = this.tweetActionIds.indexOf(tweetId)
this.tweets[i].isSelected = !this.tweets[i].isSelected
if (this.tweetActionIds.includes(tweetId)) {
this.tweetActionIds.splice(idIndex, 1)
} else {
this.tweetActionIds.push(tweetId)
}
},
markReply(replyId) {
const idIndex = this.tweetActionIds.indexOf(replyId)
if (this.tweetActionIds.includes(replyId)) {
this.tweetActionIds.splice(idIndex, 1)
} else {
this.tweetActionIds.push(replyId)
}
},
},
}
</script>
I have tried to add replySelected in data and then when click is triggered in markReply i changed replySelected to true, but every reply of a tweet was then selected, which is not what i want.
If I understood you correctly try like following snippet:
const app = Vue.createApp({
data() {
return {
tweets: [{id: 1, tweet_id: 1, isSelected: true, tweet_text: 'aaa', tweetReplies: [{tweet_id: 11, tweet_text: 'bbb'}, {tweet_id: 12, tweet_text: 'ccc'}]}, {id: 2, tweet_id: 2, isSelected: false, tweet_text: 'ddd', tweetReplies: [{tweet_id: 21, tweet_text: 'eee'}, {tweet_id: 22, tweet_text: 'fff'}]}],
tweetActionIds: [],
}
},
methods: {
markTweet(tweetId, i) {
const idIndex = this.tweetActionIds.indexOf(tweetId)
this.tweets[i].isSelected = !this.tweets[i].isSelected
if (this.tweetActionIds.includes(tweetId)) {
this.tweetActionIds.splice(idIndex, 1)
} else {
this.tweetActionIds.push(tweetId)
}
},
markReply(replyId) {
const idIndex = this.tweetActionIds.indexOf(replyId)
if (this.tweetActionIds.includes(replyId)) {
this.tweetActionIds.splice(idIndex, 1)
} else {
this.tweetActionIds.push(replyId)
}
},
checkReply(r) {
return this.tweetActionIds.includes(r) ? true : false
}
},
})
app.mount('#demo')
.selected {color: red;}
<script src="https://cdn.jsdelivr.net/npm/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div class="container-full">
<div class="tweets-container">
<div v-for="(tweet, i) in tweets" :key="tweet.id">
<div
class="tweet-card"
:class="{ selected: tweet.isSelected }"
#click="markTweet(tweet.tweet_id, i)"
>
<div class="text">
<p v-html="tweet.tweet_text">
{{ tweet.tweet_text }}
</p>
</div>
</div>
<div class="replies">
<div
v-for="(reply, index) in tweet.tweetReplies"
:key="reply.tweet_id"
#click="markReply(reply.tweet_id, index)"
>
<div class="tweet-card tweet-reply">
<div class="text" :class="{selected: checkReply(reply.tweet_id)}">
<p>{{ reply.tweet_text }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{tweetActionIds}}
</div>
You can build on Nikola's answer by bypassing the extra step of adding isSelected to each individual Tweet by just checking if it's in the tweetActionIds array, and then do the same with the replies to keep it clean
<div id="demo">
<div class="container-full">
<div class="tweets-container">
<div
v-for="(tweet, i) in tweets"
:key="tweet.id"
>
<div
class="tweet-card"
:class="{ selected: isActive(tweet) }"
#click="markTweet(tweet.tweet_id, i)"
>
<div class="text">
<p v-html="tweet.tweet_text">
{{ tweet.tweet_text }}
</p>
</div>
</div>
<div class="replies">
<div
v-for="(reply, index) in tweet.tweetReplies"
:key="reply.tweet_id"
#click="markReply(reply.tweet_id, index)"
>
<div
:class="{ selected: isActive(reply) }"
class="tweet-card tweet-reply"
>
<div class="text">
<p>{{ reply.tweet_text }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{tweetActionIds}}
</div>
const app = Vue.createApp({
data() {
return {
tweets: []
tweetActionIds: [],
categories: [],
}
},
methods: {
markTweet(tweetId, i) {
const idIndex = this.tweetActionIds.indexOf(tweetId)
if (this.tweetActionIds.includes(tweetId)) {
this.tweetActionIds.splice(idIndex, 1)
} else {
this.tweetActionIds.push(tweetId)
}
},
markReply(replyId) {
const idIndex = this.tweetActionIds.indexOf(replyId)
if (this.tweetActionIds.includes(replyId)) {
this.tweetActionIds.splice(idIndex, 1)
} else {
this.tweetActionIds.push(replyId)
}
},
isSelected(tweet) {
return this.tweetActionIds.includes(tweet.tweet_id);
}
},
})

Vue: How pass the data to another component (with database)

I'm trying to get a clicked button id from MovieTable.vue to WatchedForm.vue component. WatchedForm.vue component updates the data in the database based on the given id. So this Movie_id is the id obtained from the database. I've already tried using props, but I didn't get it to work. Please help! I'm losing my mind..
App.vue:
<template>
<div class="container p-5">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#movieModal">
Add Movie
</button>
<movie-form #add:movie="addMovie" />
<movie-table
:movies="movies"
#delete:movie="deleteMovie"
#edit:movie="WatchedMovie"
#edit2:movie="unWatchedMovie"
/>
</div>
<watched-form
#edit:movie="watchedMovie"
#edit2:movie="unWatchedMovie"
/>
</template>
<script>
//importing bootstrap 5
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.min.js";
import MovieTable from '#/components/MovieTable.vue';
import MovieForm from '#/components/MovieForm.vue';
import WatchedForm from '#/components/WatchedForm.vue';
export default {
components: {
MovieTable,
MovieForm,
WatchedForm
},
data() {
return {
movies: {},
}
},
mounted() {
this.getMovies()
},
methods: {
async getMovies() {
try {
const response = await fetch('http://localhost:8081/api/movies')
const data = await response.json()
this.movies = data
} catch (error) {
console.error(error)
}
},
async addMovie(movie) {
try {
const response = await fetch('http://localhost:8081/api/addMovie', {
method: 'POST',
body: JSON.stringify(movie),
headers: {"Content-type": "application/json; charset=UTF-8"}
})
const data = await response.json()
this.movies = [...this.movies, data]
} catch (error) {
console.error(error)
}
},
async deleteMovie(Movie_id) {
try {
await fetch(`http://localhost:8081/api/delete/${Movie_id}`, {
method: 'DELETE'
})
this.movies = this.movies.filter(movie => movie.Movie_id !== Movie_id)
} catch (error) {
console.error(error)
}
},
async watchedMovie(Movie_id, updatedMovie) {
try {
const response = await fetch(`http://localhost:8081/api/movies/watched/${Movie_id}`, {
method: 'PUT',
body: JSON.stringify(updatedMovie),
headers: { "Content-type": "application/json" }
})
const data = await response.json()
this.movies = this.movies.map(movie => movie.Movie_id === Movie_id ? data : movie)
} catch (error) {
console.error(error)
}
},
async unWatchedMovie(Movie_id, updatedMovie) {
try {
const response = await fetch(`http://localhost:8081/api/movies/unwatched?id=${Movie_id}`, {
method: 'PUT',
body: JSON.stringify(updatedMovie),
headers: { "Content-type": "application/json" }
})
const data = await response.json()
this.movies = this.movies.map(movie => movie.Movie_id === Movie_id ? data : movie)
this.movies = this.getMovies();
} catch (error) {
console.error(error)
}
}
}
}
</script>
MovieTable.vue:
<template>
<div id="movie-table">
<p v-if="movies.length < 1" class="empty-table">No movies</p>
<table v-else>
<thead>
<tr>
<th>Name</th>
<th>Genre</th>
<th>Duration</th>
<th>Rating</th>
<th>Watched?</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr :key="movie.Movie_id" v-for="movie in movies " :id="'form' + movie.Movie_id">
<td>{{movie.Name}}</td>
<td>{{movie.Genre}}</td>
<td>{{movie.Duration}}</td>
<td>{{movie.Rating}}</td>
<td>
<span v-if="movie.is_watched">Yes</span>
<span v-else>No</span>
</td>
<td>
<button type="button" class="btn btn-primary" #click="unWatchedMovie(movie)" v-if="movie.is_watched === 1">
Unwatched
</button>
<!-- THIS BUTTON ID I WANT TO GET -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#watchedModal" #click="watchedMovie( movie)" v-else>
Watched
</button>
<button class="btn btn-primary" #click="$emit('delete:movie', movie.Movie_id)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'movie-table',
props: {
movies: Array
},
data() {
return {
editing: null,
}
},
methods: {
watchedMovie(movie) {
if (movie.Name === '' || movie.Genre === '' || movie.Duration === '' || movie.is_watched === '') return
this.$emit('edit:movie', movie.Movie_id, movie)
this.editing = null
},
unWatchedMovie(movie) {
if (movie.Name === '' || movie.Genre === '' || movie.Duration === '' || movie.is_watched === '') return
this.$emit('edit2:movie', movie.Movie_id, movie)
this.editing = null
},
handler(id) {
console.log(id);
}
}
}
And WatchedForm.vue:
<template>
<div id="watched-form">
<div class="modal fade" id="watchedModal" tabindex="-1" aria-labelledby="watchedModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title text-danger" id="watchedModalLabel">Add new view</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form #submit.prevent="handleSubmit">
<!-- TRYING THERE TO SHOW ID FROM MOVIETABLE -->
<div id="watched-form1">{{movie.movie_id}}</div>
<div class="mb-3">
<label class="form-label">Place</label>
<input ref="first"
type="text"
v-model="movie.Place"
#focus="clearStatus"
#keypress="clearStatus"
class="form-control"
/>
</div>
<div class="mb-3">
<label class="form-label">Date</label>
<input
type="Date"
v-model="movie.Date"
#focus="clearStatus"
class="form-control"
/>
</div>
<div class="mb-3">
<label class="form-label">Rating 1-5</label>
<input
type="number"
min="1"
max="5"
:class="{ 'has-error': submitting && invalidRating}" class="form-control"
v-model="movie.Rating"
#focus="clearStatus"
/>
</div>
<div class="mb-3">
<label class="form-label">Comments</label>
<textarea class="form-control" v-model="movie.Comments" #focus="clearStatus"></textarea>
</div>
<div class="mb-3">
<label class="form-label">Watched?</label>
<input
type="checkbox"
v-model="movie.is_watched.checked"
#focus="clearStatus"
checked
disabled
/>
</div>
<p v-if="error && submitting" class="error-message">❗Please fill out rating required field</p>
<p v-if="success" class="success-message">✅ Movie successfully added</p>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'watched-form',
data() {
return {
submitting: false,
error: false,
success: false,
movie: {
Name: '',
Genre: '',
Duration: '',
Rating: '',
is_watched: '',
}
}
},
methods: {
handleSubmit() {
this.clearStatus()
this.submitting = true
if (this.invalidRating ) {
this.error = true
return
}
this.$emit('edit:movie', this.movie)
this.$refs.first.focus()
this.movie = {
Name: '',
Genre: '',
Duration: '',
Rating: '',
is_watched: ''
}
this.error = false
this.success = true
this.submitting = false
},
clearStatus() {
this.success = false
this.error = false
},
},
computed: {
invalidRating() {
return this.movie.Rating === ''
}
},
}
</script>
You just need to do the below changes in App.vue, when you emit the movie id from MovieTable.vue, you got to send it as props to WatchedForm.vue not as a variable instead as a computed property. Check the below approach
<movie-table
:movies="movies"
#delete:movie="deleteMovie"
#edit:movie="WatchedMovie"
#edit2:movie="unWatchedMovie"
/>
</div>
<watched-form
:movieId="getMovieId"
/>
and add a variable called movieId inside data() like
data() {
return {
movieId: '',
....other variables
};
}
and in computed
computed: {
getMovieId() {
return this.movieId;
}
}
and in your methods where you set the movieId that is emitted from MovieTable.vue such that the computed property runs dynamically
methods: {
async watchedMovie(Movie_id, updatedMovie) {
this.movieId = Movie_id; // setting the movie_id in localvariable so that the computed property sends the updated value to WatchedForm.vue
// ...Other lines of code
},
async unWatchedMovie(Movie_id, updatedMovie) {
this.movieId = Movie_id; // setting the movie_id in localvariable so that the computed property sends the updated value to WatchedForm.vue
// ...Other lines of code
}
}

Do these two Axios and github url have a difference

<template>
<div class="ls-repo">
<div
class="row justify-content-between ls-pin-repo"
v-for="repo in repos"
:key="repo.id"
>
<div class="col-md-6">
<router-link :to="repo.html_url"
><h6>{{ repo.name }}</h6></router-link
>
<div class="row ls-r">
<div class="col mt-4">
<span>{{ repo.language }}</span>
</div>
</div>
</div>
<div class="col-md-6">
{{ repo.full_name }} <br />
{{ repo.visibility }}
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "Repositories",
data() {
return {
repos: null,
search: "",
};
},
methods: {
setData(data) {
this.repos = data;
console.log(this.repos.node_id);
},
searchData() {
axios
.get("https://api.github.com/repos/dimaswntech/" + this.search, {
headers: {
Authorization: "token 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",
},
})
.then((response) => {
this.setData(response.data);
console.log(response.data);
})
.catch((error) => console.log(error));
console.log(this.search);
},
},
mounted() {
axios
.get("https://api.github.com/users/dimaswntech/repos", {
headers: {
Authorization: "token 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",
},
})
.then((response) => {
this.setData(response.data);
console.log(this.repos);
})
.catch((error) => console.log(error));
},
};
</script>
<style></style>
Im sorry friends, let me ask something. I am use vue js and i will fetch data from api github. In my method with name "seachData()" and Mounted part, i use axios. But i don't know, i got an error if i fill the input tag like this
<input
class="form-control input-repo"
type="text"
v-model="search"
v-on:keyup.enter="searchData"
/>
And my error said. my code has variable with null value. i those code i did not fill the input tag. So i hope you guys can help me.

What is a good way to call a function that makes an axios request using information from within a v-for?

I am working on an e-commerce site using rails and VueJS. I have a component file to display the orders of a given user. I am using a v-for loop to iterate and display all the user's order info. each order is linked to a carted products table where the product I.D. is located. I want to display the product information of each product within each order. I have a productShow function that makes an axios request to the backend and retrieves the product's info, the problem is I'm not sure how to capture the product ID from each of the products in the carted product array to send with the request. Even if I manage that how would I display each product within each order and the order's info as well? I have been unsuccessful in my attempts thus far and am looking for some guidance. code and info below.
ordersIndex.Vue component:
<div class="home">
<h1>{{ message }}</h1>
<div v-for="order in orders">
<h2>Order Number:{{ order.id }}</h2>
<h1 v-for="cartedProduct in order.carted_products"> <strong>{{ cartedProduct }}</strong> </h1>
<h3>SUBTOTAL:{{ order.subtotal }}</h3>
<h3>TAX:{{ order.tax }}</h3>
<h3>TOTAL: {{ order.total }}</h3>
</div>
</div>
</template>
<style>
</style>
<script>
import axios from "axios";
export default {
data: function () {
return {
message: "Your Orders",
orders: [],
anOrder: [],
cartedProducts: [],
product: {},
productId: "",
};
},
created: function () {
console.log("In Created...");
this.orderIndex();
// this.cartedProductsonOrder();
},
methods: {
orderIndex: function () {
console.log("In orderIndex...");
axios.get("/api/orders").then((response) => {
console.log(response.data);
this.orders = response.data;
this.cartedProductsonOrder();
});
},
productShow: function (id) {
console.log("in products show");
axios.get("/api/products/" + id).then((response) => {
console.log(response.data);
this.product = response.data;
console.log("Line 53");
console.log(this.product);
this.cartedProducts.push(this.product);
console.log(this.cartedProducts);
});
},
cartedProductsonOrder: function () {
console.log("In cartedProductsonOrder method....");
console.log(this.orders);
for (let i = 0; i < this.orders.length; i++) {
console.log("Line 62");
console.log(this.orders[i].carted_products);
this.cartedProducts = this.orders[i].carted_products;
for (let j = 0; j < this.cartedProducts.length; j++) {
console.log("Line 67");
console.log(this.cartedProducts[j]);
console.log(this.cartedProducts[j].product_id);
this.productId = this.cartedProducts[j].product_id;
this.productShow(this.productId);
}
}
},
},
};
</script>
Screenshots of console log:
order response
carted products
This is completely untested however, it should give you a good idea of how to accomplish what you're after. I have also made a few other changes such as using fat arrow functions and changing to forEach loops instead of basic for loops.
<template>
<div class="home">
<h1>{{ message }}</h1>
<div v-for="order in orders">
<h2>Order Number:{{ order.id }}</h2>
<h1 v-for="product in order.carted_products"> <strong>{{ cartedProduct }}</strong> </h1>
<h3>SUBTOTAL:{{ order.subtotal }}</h3>
<h3>TAX:{{ order.tax }}</h3>
<h3>TOTAL: {{ order.total }}</h3>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
data: () => ({
message: "Your Orders",
orders: [],
cartedProducts: []
}),
mounted: {
this.doGetOrders()
},
methods: {
doGetOrders: () => {
axios.get(`/api/order`).then((response) => {
this.orders = response.data
this.doCartedProductsInOrder()
})
},
doCartedProductsInOrder: () => {
if (this.order.length >= 1) {
this.order.forEach((order) => {
if (order.cartedProducts >= 1) {
order.cartedProducts.forEach((product) => {
this.cartedProducts.push(this.doGetProductInfo(productId))
})
}
})
}
},
doGetProductInfo: (productId) => {
axios.get(`/api/products/${productId}`).then((response) => {
if (response.status === 200) {
return response.data
}
})
}
}
}
</script>

How to parse json in Vue js to use it in template

<template>
<div class="row w-20 " >
<div class="card col-4 ">
<ul>
<li v-for="message in conversations.messages" :key="message.messages">
{{message.text}}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: ['conversation_index_route'],
data() {
return {
conversations: [],
url: 'http://127.0.0.1:8000/comms/conversation/',
}
},
beforeMount() {
this.$eventBus.$on('selectConversation', this.getConversations)
this.getConversations();
},
methods: {
getConversations(id) {
console.log(this.url+id);
axios.get(this.url+ id)
.then(response => {
this.conversations = response.data;
this.conversations = JSON.parse(this.conversations.message);
console.log(this.conversations);
});
}
}
}
</script>
conversation_index_route:"http://127.0.0.1:8000/comms/conversation"
conversations:Object
all_staff_attended:false
centre_id:5
children:""
classes:""
cover_image:"https://via.placeholder.com/150x150"
created_at:"2020-05-30 19:01:59"
exited_users:null
id:257
last_id:null
messages:Array[1]
0:"{"_id":1854,"text":"This is the beginning of this conversation","createdAt":"2020-05-30 19:01:59","system":true}"
parent_users:"3016"
parents:Array[1]
staff_users:"180,181"
staffs:Array[2]
status_id:1
title:"Test"
updated_at:"2020-05-30 19:01:59"
url:"http://127.0.0.1:8000/comms/conversation/"
So what shall I code to use the message text in my template to display the text messages?
You'd have to do JSON.parse(conversations.messages[0]).text. This way you parse the object inside messages and have access to its properties.
Simply JSON.parse the string
var myJson = "[{\"id\":72,\"food_item_id\":\"56\",\"variation_id\":\"20\",\"price\":\"50\",\"created_at\":\"2021-06-29T05:29:14.000000Z\",\"updated_at\":\"2021-06-29T05:29:14.000000Z\",\"variant\":null}]";
var myJson2 = JSON.parse(myJson);
console.log(myJson2);

Categories