I'm trying to create a simple marketcap checker for crytpo (like coinmarketcap) using coingecko api.
I can fetch the data and render it, no problem with that. And I fetch the data 2 times per minutes.
But now, I would like to check if the new price is higher or lower than the last price.
I do a v-for loop and I pass some data in my "tokenComponent" for rendering the data like this :
<template>
<div id="app">
<div class="container mx-auto">
<div class="pt-6">
<h1 class="text-2xl font-bold">Crypto Monkey Cap</h1>
<div v-for="token in listTokens" :key="token.id">
<div class="py-6">
<token-component
:name="token.name"
:price="token.current_price"
:mcap="token.market_cap"
></token-component>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import TokenComponent from "./components/tokenComponent.vue";
export default {
name: "App",
components: {
TokenComponent,
},
data() {
return {
listTokens: [],
lastPrice: 0
};
},
mounted() {
this.getTokens();
setInterval(() => {
this.getTokens()
}, 30000);
},
methods: {
getTokens() {
fetch("https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd")
.then((response) => response.json())
.then((data) => {
this.listTokens = data;
});
}
}
};
</script>
and the tokenComponent :
<template>
<div class="py-4 border-2 rounded-lg">
<div class="flex justify-around">
<h2>{{ name }}</h2>
<h2>{{ price }} $</h2>
<h2>{{ mcap }} $</h2>
</div>
</div>
</template>
<script>
export default {
props: {
name: { required: true },
price: { required: true },
mcap: { required: true }
}
};
</script>
I just would like put a conditionnal class in price data if the last price is higher or lower than the new one...
(I'm new in Vuejs... ;) )
You should store previous prices to calculate if the last price is higher or lower than the new one. Use Array for that.
Added small example using setInterval instead of fetching new prices to display indicators
new Vue({
el: "#app",
data: () => ({
prices: [1]
}),
methods: {
stonks(index) {
if (index > 0) {
return (this.prices[index] - this.prices[index-1]) > 0
? 'green' : 'red'
}
}
},
mounted() {
setInterval(() => {
this.prices.push(Math.floor(Math.random() * 10) + 1)
}, 2000)
}
})
.prices {
display: flex;
flex-direction: row;
padding: 10px;
}
.price {
border:1px solid #bbb;
border-radius: 5px;
padding: 10px;
width: 32px;
height: 32px;
line-height: 32px;
text-align: center;
margin-right: 5px;
position: relative;
}
.stonks {
position: absolute;
background: grey;
border-radius: 50%;
width: 16px;
height: 16px;
top: 0;
right: 0;
margin-top:-8px;
margin-right:-8px
}
.stonks.red { background: red; }
.stonks.green { background: green; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="prices">
<div
v-for="(price, index) in prices"
:key="index"
class="price"
>
{{ price }}
<div class="stonks" :class="stonks(index)" />
</div>
</div>
</div>
Related
I just started programming and I don't know how to do this. Every help is welcome.
I have a mini pokemon game that gives me random from the first 151 pokemon and when I answer correctly I want to save that pokemon in the json database from the logged in user in the array user_pokedex.
And I want to save the id of that correct aswered pokemon in one array so that I can use that array later so that those pokemons are no longer shown in the game for that user
This is my db.js local database :
{
"users": [
{
"username": "Trpimir",
"email": "ttom#gmail.com",
"password": "Password123",
"id": 1,
"user_pokedex": []
},
{
"username": "user2",
"email": "user1#gmail.com",
"password": "user12345",
"id": 2,
"user_pokedex": []
}
]
}
This is my game.vue component where the game is:
<script setup lang="ts">
import { ArrowRight,} from '#element-plus/icons-vue'
import { ref, computed } from 'vue'
import axios from 'axios';
import { pokeStore } from '../store/pokemonStore'
import { usePokedexStore } from '../store/pokedexStore';
import { useLoginStore } from '../store/loginStore';
import { useGameStore } from '../store/gameStore';
const PokemonStore = pokeStore();
const pokedexStore = usePokedexStore();
let gameStore = useGameStore()
let correct = ref<boolean>(false)
let inccorect = ref<boolean>(false)
let pokemonName = ref<string>('')
let isLoading = ref<boolean>(true)
let randomPokemon = ref<any>()
async function getRandomPokemon() {
isLoading.value = true
correct.value = false
inccorect.value = false
try {
let response = await PokemonStore.getOnePokemon();
randomPokemon.value = response;
console.log(randomPokemon.value)
isLoading.value = false
} catch (error) {
throw error;
}
}
getRandomPokemon()
function submitAnswer(){
pokemonName.value = pokemonName.value.toLowerCase()
if(pokemonName.value == randomPokemon.value.name){
inccorect.value = false
correct.value = true
pokemonName.value = ''
setTimeout(function() {
getRandomPokemon()
}, 1500);
} else{
console.log("Incorrect answer")
correct.value = false
inccorect.value = true
pokemonName.value = ''
}
}
</script>
<template>
<el-dialog v-if="!isLoading" v-model="gameStore.showModal" width="35%" height="50%" center #keyup.enter="submitAnswer" >
<template #header>
<img class="whosThatPokeImg" src="/src/assets/images/Whos-that-Pokemon.png" />
</template>
<template #default>
<div class="modalHeader">
<img :src="randomPokemon.image" width="250" height="250" />
</div>
<div class="footer">
<div class="inputDiv">
<input v-model="pokemonName" class="pokeNameInput" onfocus="this.value=''" type="text" placeholder="This pokemon is ..." maxlength="20" minlength="4" />
</div>
<div v-if="inccorect" class="incorrect">
<el-row justify="center">
<span class="incorrectBold">Incorrect answer!</span>
</el-row>
</div>
<div v-if="correct" class="correct">
<el-row justify="center">
<span class="correctBold">Correct answer!</span>
</el-row>
</div>
<span>
<el-button id="submitBtn" #click="submitAnswer()" :disabled="!pokemonName.length">Submit</el-button>
<el-button id="skipBtn" #click="getRandomPokemon() ">Skip
<el-icon class="el-icon--right"><ArrowRight /></el-icon></el-button>
<el-button id="pokedexGameBtn" #click="pokedexStore.changeModal()">Pokedex</el-button>
</span>
</div>
</template>
</el-dialog>
</template>
<style scoped>
.footer{
text-align: center;
padding-top: 10px;
}
.pokeNameInput{
padding: 5px;
border-radius: 4px;
font-size: 14px;
width: 57%;
background-color: transparent;
text-align: center;
}
.inputDiv{
padding-bottom: 15px;
}
#skipBtn{
background-color: #FFD700;
border: 1.5px solid black;
}
#submitBtn{
background-color:black;
border: 1.5px solid black;
color: yellowgreen;
}
#pokedexGameBtn{
background-color:whitesmoke;
border: 1.5px solid black;
}
.modalHeader{
text-align: center;
}
.el-dialog{
opacity: 0.8;
}
.whosThatPokeImg{
width: 100%;
max-width: 85%;
text-align: center;
}
.incorrect{
padding-bottom: 15px;
color: red;
}
.correct{
padding-bottom: 15px;
color: green;
}
.correctBold, .incorrectBold{
font-weight: bold;
}
</style>
This is pokemonStore.js where i het random pokemon from API:
import { defineStore } from 'pinia'
import axios from 'axios'
let apiLink = 'https://pokeapi.co/api/v2'
export const pokeStore = defineStore("pokemons", {
state: () => {
return {
pokemons: []
};
},
actions: {
async getOnePokemon() {
try {
let id = Math.floor(Math.random() * 151) + 1;
let response = await axios.get(`${apiLink}/pokemon/${id}`)
if(response.data){
let pokemon = {
id: response.data.id,
name: response.data.name,
image: response.data.sprites.front_default
}
return pokemon
}
} catch (error) {
console.log(error)
}
},
}
});
So I have a problem with VueJs. I created a "Confirmation Dialogue" and added it to a On-Click-Event on buttons. It worked fine.
Now I tried to copy the implementation to add it to another button on a different parent. It says "TypeError: this.$refs.confirmDialogue.show is not a function" in the Console whenever I try to click the button. The other button still works completly normal.
Am I missing something? I already tried to remove the working button, so only one component uses the Confirm Dialogue but that also didn't work.
I'm new to VueJs. Hope someone can help me with this problem.
Child PopupModal:
<template>
<transition name="fade">
<div class="popup-modal" v-if="isVisible">
<div class="window">
<slot></slot>
</div>
</div>
</transition>
</template>
<script>
export default {
name: 'PopupModal',
data: () => ({
isVisible: false,
}),
methods: {
open() {
this.isVisible = true
},
close() {
this.isVisible = false
},
},
}
</script>
<style scoped>
/* css class for the transition */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.popup-modal {
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 0.5rem;
display: flex;
align-items: center;
z-index: 1;
}
.window {
background: #fff;
border-radius: 5px;
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2);
max-width: 480px;
margin-left: auto;
margin-right: auto;
padding: 1rem;
}
</style>
Parent ConfirmDialogue:
<template>
<popup-modal ref="popup">
<h2 style="margin-top: 0">{{ title }}</h2>
<p>{{ message }}</p>
<div class="btns">
<button class="cancel-btn" #click="_cancel">{{ cancelButton }}</button>
<span class="ok-btn" #click="_confirm">{{ okButton }}</span>
</div>
</popup-modal>
</template>
<script>
import PopupModal from "../confirmDialogue/PopupModal.vue"
export default {
name: 'ConfirmDialogue',
components: { PopupModal },
data: () => ({
// Parameters that change depending on the type of dialogue
title: undefined,
message: undefined, // Main text content
okButton: undefined, // Text for confirm button; leave it empty because we don't know what we're using it for
cancelButton: 'Abbrechen', // text for cancel button
// Private variables
resolvePromise: undefined,
rejectPromise: undefined,
}),
methods: {
show(opts = {}) {
this.title = opts.title
this.message = opts.message
this.okButton = opts.okButton
if (opts.cancelButton) {
this.cancelButton = opts.cancelButton
}
// Once we set our config, we tell the popup modal to open
this.$refs.popup.open()
// Return promise so the caller can get results
return new Promise((resolve, reject) => {
this.resolvePromise = resolve
this.rejectPromise = reject
})
},
_confirm() {
this.$refs.popup.close()
this.resolvePromise(true)
},
_cancel() {
this.$refs.popup.close()
this.resolvePromise(false)
// Or you can throw an error
// this.rejectPromise(new Error('User cancelled the dialogue'))
},
},
}
</script>
<style scoped>
.btns {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.ok-btn {
padding: 0.5em 1em;
background-color: #1F51FF;
color: #fff;
border: 2px solid #0ec5a4;
border-radius: 5px;
font-size: 16px;
text-transform: uppercase;
cursor: pointer;
}
.cancel-btn {
padding: 0.5em 1em;
background-color: #d5eae7;
color: #000;
border: 2px solid #0ec5a4;
border-radius: 5px;
font-size: 16px;
text-transform: uppercase;
cursor: pointer;
}
</style>
Working button:
<td class="last-td last-row">
<div class="button-wrapper">
<div class="wrapper-edit">
<button class="button button-edit">Bearbeiten</button>
</div>
<div class="wrapper-cancel">
<button class="button button-cancel" #click="doDelete">Löschen</button> <!-- Here is the working button -->
<confirm-dialogue ref="confirmDialogue"></confirm-dialogue>
</div>
</div>
</td>
</tr>
</thead>
</template>
<script>
import ConfirmDialogue from '../confirmDialogue/ConfirmDialogue.vue'
export default {
name: "bookingElements",
components: { ConfirmDialogue },
methods: {
async doDelete() {
const ok = await this.$refs.confirmDialogue.show({
title: 'Buchung löschen',
message: 'Sind Sie sicher, dass Sie die Buchung löschen wollen?',
okButton: 'Buchung löschen',
})
if (ok) {
alert('Die Buchung wurde Erfolgreich gelöscht')
}
},
Button that isn't working:
<td id="buttonCell">
<button class="button" #click="doDelete">Buchen</button>
<confirm-dialogue ref="confirmDialogue"></confirm-dialogue>
</td>
</tr>
</tbody>
</template>
<script>
import ConfirmDialogue from "../confirmDialogue/ConfirmDialogue.vue"
export default {
name: "bookElements",
components: { ConfirmDialogue },
methods: {
async doDelete() {
const ok = await this.$refs.confirmDialogue.show({
title: 'Buchung löschen',
message: 'Sind Sie sicher, dass Sie die Buchung löschen wollen?',
okButton: 'Buchung löschen',
})
if (ok) {
alert('Die Buchung wurde Erfolgreich gelöscht')
}
},
I got found the mistake.
I created a for-each loop to create the Table.
At the working button there was no for-each loop though.
So VueJs tried to generate the Confirmation Dialogue 9 times and this resulted to an error.
So I just need to put the
<confirm-dialogue ref="confirmDialogue"></confirm-dialogue>
to the top of Template like this
<template>
<confirm-dialogue ref="confirmDialogue"></confirm-dialogue>
...
</template>
because it's vanished and only shows when the button is clicked.
I am trying to scroll up a div 10px by following method in Vue2 app:
this.$refs.hello.scrollTo({ top: 10, left: 0, behavior: "smooth"});
However, instead of scroll to top 10px, it scrolls to the top. How can I scroll to a specific height.
codesandbox example : https://codesandbox.io/s/youthful-blackwell-wl5x6?file=/src/components/HelloWorld.vue:531-630
Good apprch will be, to scroll to the current scrollHeight of the reference element after updating the list.
Demo
new Vue({
el: '#app',
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
list: [],
};
},
mounted() {
let i = 0;
for (i = 0; i < 19; i++) {
this.list.push(i);
}
},
methods: {
addItem() {
this.list.push(0);
setTimeout(() => {
const targetTop = this.$refs.hello.scrollHeight;
this.$refs.hello.scrollTo({
top: targetTop,
left: 0,
behavior: "smooth",
});
})
},
}
})
.hello {
overflow-y: auto;
height: 200px;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<div id="app">
<div class="hello" ref="hello">
<h1>{{ msg }}</h1>
<div v-for="item in list" :key="item">
<div style="margin-bottom: 20px">{{ item }}</div>
</div>
<button #click="addItem">add</button>
</div>
</div>
new Vue({
el: "#app",
data: {
getQuestionAnswers: [
{
name: 'foo',
checked: false,
status: 'ok'
},
{
name: 'bar',
checked: false,
status: 'notok'
},
{
name: 'baz',
checked: false,
status: 'medium'
},
{
name: 'oo',
checked: false,
status: 'medium'
}
]
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
width:100%
}
.red {
color: red;
}
.bcom {
width: 100%;
display: flex;
}
.container1 {
width: 50px;
}
.container2 {
width: calc(100% - 105px);
padding: 8px 0;
height: 30px;
box-sizing: border-box;
}
.h-line {
height: 1px;
margin-bottom: 18px;
width: 100%;
background-color: black;
}
.container3{
margin-left: 5px;
width: 50px;
}
.point:hover {
width: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<div class="bcom"
v-for="(group, index) in getQuestionAnswers"
:key="index + group.name"
:group="group"
>
<div>
<input type="checkbox" v-model="group.checked"/>
{{ group.name }}
</div>
<div class="container2">
<div class="h-line" v-if="group.checked"></div>
</div>
<div>
<input type="checkbox"/>
{{ group.status }}
</div>
</div>
</div>
Onclick of checkbox, how to add multiple lines from one point in Vuejs?
As seen in the image, On click of the checkbox, Based on the status, I need to match from one point to three multiple status. like "ok, notok, medium"
i have taken v-model in the checkbox,to check and perfome two way data binding But not sure....what to do further. Do I need to take computed property and write condition to check and draw three multiple lines???
there are som positioning issues here, but this sample should be enough for you to get it working:
template
<div id="demo" :ref="'plane'">
<canvas :ref="'canvas'"></canvas>
<div
class="bcom"
v-for="(group, index) in getQuestionAnswers"
:key="index + group.name"
:group="group"
>
<div>
<input
type="checkbox"
v-on:click="() => onToggleCheckbox(group)"
v-model="group.checked"
:ref="'checkbox_' + group.name"
/>
<span>{{ group.name }}</span>
</div>
<div>
<span>{{ group.status }}</span>
<input type="checkbox" :ref="'status_' + group.name" />
</div>
</div>
</div>
script:
export default {
name: 'App',
data: () => ({
ctx: undefined,
draw(begin, end, stroke = 'black', width = 1) {
if (!this.ctx) {
const canvas = this.$refs['canvas'];
if (!canvas?.getContext) return;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
this.ctx = canvas.getContext('2d');
}
if (stroke) {
this.ctx.strokeStyle = stroke;
}
if (width) {
this.ctx.lineWidth = width;
}
this.ctx.beginPath();
this.ctx.moveTo(...begin);
this.ctx.lineTo(...end);
this.ctx.stroke();
},
onToggleCheckbox(group) {
const planeEl = this.$refs['plane'];
const planeRect = planeEl.getBoundingClientRect();
const fromEl = this.$refs['checkbox_' + group.name];
const fromRect = fromEl.getBoundingClientRect();
const from = {
x: fromRect.right - planeRect.left,
y: fromRect.top + fromRect.height / 2 - planeRect.top,
};
const toEl = this.$refs['status_' + group.name];
const toRect = toEl.getBoundingClientRect();
const to = {
x: toRect.left - planeRect.left,
y: toRect.top + toRect.height / 2 - planeRect.top,
};
console.log(planeRect, from, to);
this.draw(
Object.values(from),
Object.values(to),
group.checked ? 'white' : 'black',
group.checked ? 3 : 2
);
},
getQuestionAnswers: [
{
name: 'foo',
checked: false,
status: 'ok',
},
{
name: 'bar',
checked: false,
status: 'notok',
},
{
name: 'baz',
checked: false,
status: 'medium',
},
{
name: 'oo',
checked: false,
status: 'medium',
},
],
}),
};
style
body {
background: #20262e;
padding: 20px;
font-family: Helvetica;
}
#demo {
position: relative;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
canvas {
position: absolute;
background: red;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: #fff;
z-index: -1;
}
.bcom {
width: 100%;
display: flex;
justify-content: space-between;
z-index: 2;
}
this only draws one line but you could easily add the others. I figured you might change your data schema to something like:
getQuestions() {
{
name: string,
checked: boolean,
statuses: [string...],
},
getStatuses() {
{
name: string
}
but not knowing about your requirements here, I decided to post the above before making further changes. (here is the sort of refactor I was referring to: https://stackblitz.com/edit/vue-yuvsxa )
addressing first comment:
in app.vue only there is one data called[((questions))], inside question we are looping and setting the status.
this is easy to address with a bit of preprocessing:
questionsAndStatusesMixed: // such as [{...question, ...statuses}],
questions: [],
statuses: [],
mounted() {
const statusesSet = new Set()
this.questionsAndStatusesMixed.forEach(item => {
const question = {
name: item.name,
checked: item.checked,
answer: item.status // is this the answer or .. these never made sense to me,
statuses: this.statuses // assuming each question should admit all statuses/that is, draw a line to each
}
const status = {
name: item.name
}
this.questions.push(question)
statusesSet.add(status)
})
Array.from(statusesSet).forEach(item => this.statuses.push(item))
}
I have some cards in my dashboard and in the dashboard I am getting some cards which contains title and description of the card, which I am getting from backend(axios.js).Upto display section i am getting, but in my case i want to update a particular card, when i click on any card the update popup card is coming. when i click on any card it opens popup card this card purpose is to update the content based on the card id(card details stored inside notes[] array in Getnote.vue),Here my question is How to get that particular card id when user clicks on card and how to connect this thing to the back end Api for update the particular note. please help me to fix this issue
Updatenote.vue
<template>
<div class="updatecard-notes">
<form class="updatecard-container" #submit.prevent="handleSubmit" id="update-id">
<input name="title" id="name-in" v-model="title" placeholder="Title" autocomplete="off" />
<textarea name="content" id="text-in" v-model="description" placeholder="Take a note..." autocomplete="off"></textarea>
<Icon />
<button #click="updateNotes()" type="submit">Close</button>
</form>
</div>
</template>
<script>
import service from '../../service/User'
import Icon from '../../components/pages/Icon.vue'
export default {
name: 'Updatenote',
components: {
Icon
},
data() {
return {
id:'',
title:'',
description:''
}
},
methods: {
updateNotes: function() {
const updateData ={
id:this.id,
title:this.title,
description:this.description
};
service.userUpdateNote(updateData).then(response => {
console.log("update",response);
localStorage.setItem('token',response.data.token);
this.notes.push(...response.data);
})
},
}
}
</script>
<style scoped>
.updatecard-container {
/* width: 100px; */
padding: 4px 10px;
font-size: 1rem;
/* margin-left: 200px; */
margin-bottom: -200px;
margin-top: -160px;
position: fixed;
width: 620px;
height: 150px;
box-shadow: 5px 5px 10px #e0dede;
/* margin-left: 731px; */
font-family: 'Times New Roman', Times, serif;
}
form textarea {
width: 100%;
border: none;
padding: 0px 10px;
outline: none;
font-size: 1rem;
resize: none;
}
form input {
width: 90%;
border: none;
padding: 4px 10px;
margin-bottom: 10px;
margin-left: 0px;
margin-top: 2px;
font-size: 1.1rem;
}
form button {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
right: 25px;
bottom: 10px;
background: white;
color: rgb(0, 0, 0);
border: none;
width: 50px;
height: 36px;
cursor: pointer;
font-size: 1.1rem;
font-family: 'Times New Roman', Times, serif;
}
</style>
User.js
import AxiosService from '../service/axios';
const axios = new AxiosService()
export default{
userRegister(data){
return axios.postData('/register', data);
},
userLogin(data){
return axios.postData("/login",data);
},
userForgotPassword(data){
return axios.postData("/auth/sendPasswordResetLink",data);
},
userResetPassword(data){
return axios.postData("/auth/resetPassword",data);
},
userCreateNote(data){
return axios.postData("/notes",data);
},
userGetNote(){
return axios.getData("/notes");
},
userUpdateNote(id, data){
console.log("ID: ",id);
return axios.putData(`/notes/${id}`, data);
}
}
axios.js
import axios from 'axios'
axios.defaults.baseURL=process.env.VUE_APP_ROOT_URL
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token');
export default class AxiosService{
postData(url, data){
return axios.post(url, data).then(response =>{
return response;
}).catch(error=>{
return error;
})
}
getData(url){
return axios.get(url).then(response =>{
return response;
}).catch(error=>{
return error;
})
}
putData(url, data){
return axios.put(url, data).then(response=>{
return response;
}).catch(error=>{
return error;
})
}
}
Getnotes.vue
<template>
<div class="carddisplay-notes">
<div class="carddisplay-container" v-for="note in notes" :key="note.data">
<div class="carddisplay" #click="togglePopup()">
<h3>{{note.title}}</h3>
<p>{{note.description}}</p>
</div>
<div class="carddisplay-icons">
<Icon />
<button class="card-button" type="button" v-if="flag" #click="handleSubmit();ToggleButton();">Close</button>
</div>
</div>
<div class="cardupdate-popup" id="popup">
<Updatenote />
</div>
</div>
</template>
<script>
import service from '../../service/User'
import Icon from '../../components/pages/Icon.vue'
import Updatenote from '../../components/pages/Updatenote.vue'
export default {
name: 'Getnote',
components: {
Icon, Updatenote
},
data() {
return {
flag: true,
notes:[{
id:1,
title: 'notes',
description: 'display notes'
},],
}
},
methods: {
ToggleButton(){
this.flag = !this.flag;
},
async handleSubmit() {
service.userGetNote().then(response => {
this.notes.push(...response.data);
})
},
togglePopup(){
var popup=document.getElementById('popup');
popup.classList.toggle('active');
}
}
}
</script>
<style lang="scss" scoped>
#import "#/SCSS/Getnote.scss";
</style>
In GetNotes.vue create a property in the data option, which will track the currently clicked card using the id and then pass that id to the UpdateNote component.
GetNotes.vue
<template>
<div class="carddisplay-notes">
<div class="carddisplay-container" v-for="note in notes" :key="note.id">
<div class="carddisplay" #click="togglePopup(note.id)">
<h3>{{note.title}}</h3>
<p>{{note.description}}</p>
</div>
<div class="carddisplay-icons">
<Icon />
<button class="card-button" type="button" v-if="flag" #click="handleSubmit();ToggleButton();">Close</button>
</div>
</div>
<div class="cardupdate-popup" id="popup">
<Updatenote :cardId="clickedCard"/>
</div>
</div>
</template>
<script>
import service from '../../service/User'
import Icon from '../../components/pages/Icon.vue'
import Updatenote from '../../components/pages/Updatenote.vue'
export default {
name: 'Getnote',
components: {
Icon, Updatenote
},
data() {
return {
flag: true,
notes:[{
id:1,
title: 'notes',
description: 'display notes'
},],
clickedCard: '',
}
},
methods: {
ToggleButton(){
this.flag = !this.flag;
},
async handleSubmit() {
service.userGetNote().then(response => {
this.notes.push(...response.data);
})
},
togglePopup(id){
var popup=document.getElementById('popup');
popup.classList.toggle('active');
this.clickedCard = id;
}
}
}
</script>
<style lang="scss" scoped>
#import "#/SCSS/Getnote.scss";
</style>
In Updatenote component use that id to make the api call. Here the cardId will contain the id of currently clicked card.
Updatenote.vue
<template>
<div class="updatecard-notes">
<form class="updatecard-container" #submit.prevent="handleSubmit" id="update-id">
<input name="title" id="name-in" v-model="title" placeholder="Title" autocomplete="off" />
<textarea name="content" id="text-in" v-model="description" placeholder="Take a note..." autocomplete="off"></textarea>
<Icon />
<button #click="updateNotes()" type="submit">Close</button>
</form>
</div>
</template>
<script>
import service from '../../service/User'
import Icon from '../../components/pages/Icon.vue'
export default {
name: 'Updatenote',
components: {
Icon
},
props: ['cardId'],
data() {
return {
title:'',
description:''
}
},
methods: {
updateNotes: function() {
const updateData ={
id:this.cardId,
title:this.title,
description:this.description
};
service.userUpdateNote(updateData).then(response => {
console.log("update",response);
localStorage.setItem('token',response.data.token);
this.notes.push(...response.data);
})
},
}
}
</script>
<style scoped>
...........
</style>