V-for is not iterating through objects - vue.js

I have an array of coupon objects named offers:
[{ "coupon":
{ "id": "1", "name": "Coupon 1" }
},
{ "coupon":
{ "id": "2", "name": "Coupon 2" }
}]
And i try to iterate trough it like this:
<div v-for="(coupon, $index) in offers" :key="$index">
<p>{{coupon.id}}</p>
</div>
The problem is that div does not iterate anything.

<div v-for="{ coupon } in offers" :key="coupon.id">
<p>{{ coupon.name }}</p>
</div>
Dont use index as key

you have to travel through the object, the First coupon is an element name so try this. This should work
div v-for="(coupon, $index) in offers" :key="$index">
<p>{{coupon.coupon.id}}</p>
</div>

Related

how to add and get items from an array in vue3?

so I am build a shop with a cart in it and I want to add products to the cart and view them in the cart after I added them. how can I fix my code? as I stumbled across the push method of JavaScript but for some reason it does not work for me. so, how can I add items to the cart and retrieve them later?
here is my code:
shop.vue
<template>
<div class="shop">
<h1>shop</h1>
<div class="products" v-for="item in items" :key="item.id">{{ item.name }}</div>
<button #click="addToCart">Add to Cart</button>
</div>
<div class="cart">
<h1>cart</h1>
<div class="cartitems" v-for="item in cart" :key="item.id">{{ item.name }} {{ item.price }}</div>
</div>
</template>
<script>
import Products from "../db.json"
export default {
name: "shop",
data() {
return {
items: Products,
cart: []
}
},
methods: {
addToCart() {
this.cart.push(this.items.id)
}
}
}
</script>
db.json as my "db" with the products
[
{
"id": 1,
"name": "iphone",
"price": 2000
},
{
"id": 2,
"name": "galaxy",
"price": 3000
}
]
addToCart() {
this.cart.push(this.items.id)
}
There is a typo (I assume). You want to add a certain item id to the cart. this.items is an array and does not have an id property.
You actually want to pass the id as an argument to the addToCart method:
<button #click="addToCart(item.id)">Add to Cart</button>
Then grab and add it to the cart:
addToCart(id) {
this.cart.push(id)
}
Update/ Edit:
You also need to place the <button> inside the v-for loop, otherwise it will not have access to the iteration scope:
<div class="products" v-for="item in items" :key="item.id">
{{ item.name }}
<button #click="addToCart(item.id)">Add to Cart</button>
</div>

Checking if something exists in json in Vue

I've got a json API that I'm using like this:
[{
"name": "Thing",
"id": 1234,
"total": 1,
"stock": [
{
"size": "Small",
"id": 1,
"count": 10
},{
"size": "Medium",
"id": 2,
"count": 5
},{
"size": "Large",
"id": 3,
"count": 5
}
]
}]
I'm looping over these in Vue, but want to check if anything exists in the 'stock' element outside of the v-for loop.
I can use v-if to check if the overall json exists, but can't seem to narrow it down to checking if the stock element contains anything.
Any pointers?
What about a v-if & v-else condition on the length of the stocks array? If the length is greater than zero we have stocks, so display them, else, display a message. Something like this.
Vue.component('your-component', {
template:
`
<div v-for="(item, i) in items" :key="i">
<p>{{ item.name }}<p>
<p>{{ item.id }}<p>
<div v-if="item.stock && item.stock.length > 0">
<p v-for="(stock, j) in item.stock" :key="j">
There'are {{ stock.count }} of size {{ stock.size }}.
<p>
</div>
<div v-else>
Ops... stocks not available.
</div>
</div>
`,
data () {
return {
items: []
}
},
created () {
fetch('your-api')
.then((res) => res.json())
.then((res) => { this.items = res })
}
})

How to read deep JSON data using Vuejs and Axios

How would I read deep JSON data nested deep inside a file? I've tried different methods and can't seem to get this to work.
<template>
<div>
<div v-for="edu in info" :key="edu">
<div>{{ edu.section.title }}</div> // this is what im trying to get to work
</div>
<div class="card container">
{{ info }}
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
info: null
}
},
mounted() {
axios
.get('./calculus.json') // Data Below
.then(response => (this.info = response.data.edu))
.catch(error => console.log(error))
}
}
</script>
My JSON looks like this:
{
"edu": {
"1": {
"title": "Title One",
"subtitle": "Subtitle One",
"description": "Description One",
"section": {
"1": {
"title": "Section One Title",
"content": "Section One Content"
}
}
},
"2": {
"title": "Title Two",
"subtitle": "Subtitle Two",
"description": "Description Two",
"section": {
"1": {
"title": "Section One Title",
"content": "Section One Content"
}
}
}
}
}
How can I use vue-for and get the data inside the section to get it to display under the title? For example: title, section>title, section>subtitle, etc.
Given each section is also an object with weird numeric keys, you can iterate them in the same way you do info.
I would also advise you to use identifiable values instead of the entire edu object in your :key bindings.
<div v-for="(edu, eduId) in info" :key="eduId">
<div v-for="(section, sectionId) in edu.section" :key="sectionId">
{{ section.title }}
</div>
</div>
If possible, I would alter the format of your JSON data to use actual arrays instead of objects with numeric keys.
One way to browse your object deeply is to cumulate v-for on your object (and children) entries.
ie:
<div v-for="([category, books], catkey) in Object.entries(info)" :key="`category-${catkey}`">
<div>{{ category }} :</div>
<div v-for="([num, book], numkey) in Object.entries(books)" :key=`book-${catkey}-${numkey}`>
<div v-for="([field, value], valkey) in Object.entries(book)" :key=`field-${catkey}-${numkey}-${valkey}`>
{{ field }} : {{ value }}
</div>
</div>
</div>
If you find it too verbose, you may try to flatten your computed data to have the following structure:
[
{
"category": "edu",
"id": "1",
"title": "Title One",
"subtitle": "Subtitle One",
"description": "Description One",
"section": {
"1": {
"title": "Section One Title",
"content": "Section One Content"
}
}
}
]

How to loop through nested objects using v-for loop

I'm working on some practice code that deals with card information, in which you can display the chosen card's detailed information by clicking one of the cards on the screen.
As demonstrated in the screenshots, if you choose one of the yellow cards, it displays more detailed information of the chosen card with green and blue background color.
I implemented this by using v-for loop, but the problem is that the detailed card information is a JSON object that contains multiple JSON objects inside, and I haven't been successful in displaying all of the members in non-JSON form.
I found some pages (like the link below) where some ways to loop through nested objects were discussed, but it was plain JavaScript code and I couldn't use the same strategy for v-for loop.
How to loop through a plain JavaScript object with the objects as members?
I understand the idea that you should just continue the loop in case the member is another object, not a primitive data type, but I don't know how to implement the same logic in v-for loop.
Could anyone tell me how to do it?
Here is my code.
(v-for loop part)
<div v-for="(obtainedCardInfo, index) in obtainedCardsInfo">
<span v-if="cardBtnChosen && card.id == selectedCard && obtainedCardInfo.id == selectedCard">
<span class="cardInfo">DETAILED CARD INFO:</span>
<div class="cardInfoDisplay">
<div v-for="(detailedInfo,index) in obtainedCardInfo" :key="index">
<p v-if="obtainedCardInfo[index]"> {{index}} : {{obtainedCardInfo[index]}} </p>
<p v-else> {{index}} : NULL </p>
</div>
</div> <br>
</span>
</div>
and the output for my current code.
DETAILED CARD INFO:
accountId : 3917674
id : 3918534
customerId : 998774
cardRole : MAIN
cardStatus : CARD_OK
truncatedCardNumber : 524804______9042
cardTemplate : MC_CARD
cardAddress : NULL
usageLimits : [ { "code": "WEEKLY", "values": null }, { "code": "DAILY", "values": [ { "code": "ATM", "singleAmount": 200, "count": 3, "sumAmount": 300 } ] }, { "code": "MONTHLY", "values": [ { "code": "ATM", "singleAmount": null, "count": 1000, "sumAmount": 1000000 } ] } ]
expiration : { "year": 2022, "month": 6 }
pinAddress : NULL
regionAndEcommBlocking : { "ecomm": false, "africa": false, "asia": false, "europe": false, "home": false, "northAmerica": false, "oceania": false, "southAmerica": false }
The v-for simply iterate through the array or the object keys.
v-for iterates through each element in the array
v-for also iterates through the keys in the object
You should also move your logic to a computed method
<template>
<p v-for:"item, index in arr" />
{{ item }}
{{ index }}
<p v-for:"item, key in obj" />
{{ item }}
{{ key }}
<br />
</template>
<script>
export default {
data() {
return {
arr:[1,2,3,4,5],
obj: { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e' }
}
},
computed: {
// do computation here
doSomething() {
}
}
}
</script>

How to pick v-model for Vue.js draggable when using a nested list

Here is my Vue
<div id="main">
<h1>Vue Dragable For</h1>
<div class="drag">
<ul>
<li v-for="category in data">
<draggable id="category" v-model="category" :move="checkMove" class="dragArea" :options="{group:'people'}">
<div v-for="item in category" style="border: 3px;">${ item.name }</div>
</draggable>
</li>
</ul>
</div>
</div>
<script>
var vm = new Vue({
el: "#main",
delimiters:['${', '}'],
data: {{ data | tojson | safe }},
methods:{
checkMove: function(evt){
console.log(evt.draggedContext.index);
console.log(evt.draggedContext.futureIndex);
console.log(evt.from.id);
console.log(evt.to.id);
axios.post('/categorize', {
'index': JSON.stringify(evt.draggedContext.index),
'futureIndex': JSON.stringify(evt.draggedContext.futureIndex),
'from':evt.to.id,
'to':evt.from.id,
});
return true
}
}
});
</script>
the data rendered in the template {{ data | tojson | safe }} just looks like:
{"data": {"uncategorized": [{"name": ""}, {"name": "first"}, {"name": "another"}]}}
Right now I am getting this error
You are binding v-model directly to a v-for iteration alias. This will not be able to modify the v-for source array because writing to the alias is like modifying a function local variable. Consider using an array of objects and use v-model on an object property instead.
so I don't think it it likes how I am using v-model. I am basing my code on this example: https://jsfiddle.net/dede89/32ao2rpm/ which uses raw son names in its v-model tags, but I cannot do that. So how should I do this?
Thanks!
I fixed this by changing my data object so that I can reference an object property on the v-model instead. Basically exactly what it said in the error. Specifically, it looks like:
<li v-for="(object,category) in data">
<h3>${ object.name }</h3>
<draggable v-bind:id="object.name"
v-model="object.items"
:id="'category-' + category"
:move="checkMove" class="dragArea"
:options="{group: 'items'}">
<div v-for="(item,key) in object.items" :id="item.id">
<a href="{{ url_for('view',itemid=${ item.id }) }}">
${ item.name }
</a>
</div>
</draggable>
</li>
with the data object like so:
{"data": {
"category2": {
"category_id": 2,
"items": [],
"name": "category2"
},
"category3": {
"category_id": 3,
"items": [],
"name": "category3"
},
"uncategorized": {
"category_id": 1,
"items": [
{ "id": 1, "name": "first!" }
],
"name": "uncategorized"
}
}}