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>