I'm trying to fetch product data from a JSON file, but can't get it to work. I've tried several things and searched the internet for a solution but none of the examples on the internet equals my situation. I'm new to both vue and axios, so please excuse my ignorance.
This is what I have so far:
Vueponent('products',{
data: {
results: []
},
mounted() {
axios.get("js/prods.json")
.then(response => {this.results = response.data.results})
},
template:`
<div id="products">
<div class="productsItemContainer" v-for="product in products">
<div class="productsItem">
<div class="">
<div class="mkcenter" style="position:relative">
<a class="item">
<img class="productImg" width="120px" height="120px" v-bind:src="'assets/products/' + product.image">
<div class="floating ui red label" v-if="product.new">NEW</div>
</a>
</div>
</div>
<div class="productItemName" >
<a>{{ product.name }}</a>
</div>
<div class="mkdivider mkcenter"></div>
<div class="productItemPrice" >
<a>€ {{ product.unit_price }}</a>
</div>
<div v-on:click="addToCart" class="mkcenter">
<div class="ui vertical animated basic button" tabindex="0">
<div class="hidden content">Koop</div>
<div class="visible content">
<i class="shop icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
`
})
new Vue({
el:"#app",
});
The json file is as follows
{
"products":[
{
"name": "Danser Skydancer",
"inventory": 5,
"unit_price": 45.99,
"image":"a.jpg",
"new":true
},
{
"name": "Avocado Zwem Ring",
"inventory": 10,
"unit_price": 123.75,
"image":"b.jpg",
"new":false
}
]
}
The problem is only with the fetching of the data from a JSON file, because the following worked:
Vueponent('products',{
data:function(){
return{
reactive:true,
products: [
{
name: "Danser Skydancer",
inventory: 5,
unit_price: 45.99,
image:"a.jpg",
new:true
},
{
name: "Avocado Zwem Ring",
inventory: 10,
unit_price: 123.75,
image:"b.jpg",
new:false
}
],
cart:0
}
},
template: etc.........
I'm trying to fetch product data from a JSON file, but can't get it to work. I've tried several things and searched the internet for a solution but none of the examples on the internet equals my situation. I'm new to both vue and axios, so please excuse my ignorance.
This is what I have so far:
Vue.ponent('products',{
data: {
results: []
},
mounted() {
axios.get("js/prods.json")
.then(response => {this.results = response.data.results})
},
template:`
<div id="products">
<div class="productsItemContainer" v-for="product in products">
<div class="productsItem">
<div class="">
<div class="mkcenter" style="position:relative">
<a class="item">
<img class="productImg" width="120px" height="120px" v-bind:src="'assets/products/' + product.image">
<div class="floating ui red label" v-if="product.new">NEW</div>
</a>
</div>
</div>
<div class="productItemName" >
<a>{{ product.name }}</a>
</div>
<div class="mkdivider mkcenter"></div>
<div class="productItemPrice" >
<a>€ {{ product.unit_price }}</a>
</div>
<div v-on:click="addToCart" class="mkcenter">
<div class="ui vertical animated basic button" tabindex="0">
<div class="hidden content">Koop</div>
<div class="visible content">
<i class="shop icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
`
})
new Vue({
el:"#app",
});
The json file is as follows
{
"products":[
{
"name": "Danser Skydancer",
"inventory": 5,
"unit_price": 45.99,
"image":"a.jpg",
"new":true
},
{
"name": "Avocado Zwem Ring",
"inventory": 10,
"unit_price": 123.75,
"image":"b.jpg",
"new":false
}
]
}
The problem is only with the fetching of the data from a JSON file, because the following worked:
Vue.ponent('products',{
data:function(){
return{
reactive:true,
products: [
{
name: "Danser Skydancer",
inventory: 5,
unit_price: 45.99,
image:"a.jpg",
new:true
},
{
name: "Avocado Zwem Ring",
inventory: 10,
unit_price: 123.75,
image:"b.jpg",
new:false
}
],
cart:0
}
},
template: etc.........
Share
Improve this question
edited Feb 9, 2019 at 17:53
MK01111000
asked Feb 9, 2019 at 17:30
MK01111000MK01111000
8322 gold badges10 silver badges21 bronze badges
7
-
What do you see in the console? Also, you will want to
v-for
theresults
rather thanproducts
, unless that is a typo... – Yom T. Commented Feb 9, 2019 at 17:40 - The console shows the following: vue.js:616 [Vue warn]: The "data" option should be a function that returns a per-instance value in ponent definitions. – MK01111000 Commented Feb 9, 2019 at 17:49
- and<br> vue.js:616 [Vue warn]: Property or method "products" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based ponents, by initializing the property. See: vuejs/v2/guide/…. found in ---> <Products> <Root> – MK01111000 Commented Feb 9, 2019 at 17:49
- Are you running Vue with CDN? – Yom T. Commented Feb 9, 2019 at 17:54
-
No I downloaded it. Both Vue and Axios work properly. The problem isnt with the files. The following displays the correct data in the console
axios.get('/js/products.json') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) .then(function () { // always executed });
– MK01111000 Commented Feb 9, 2019 at 17:57
1 Answer
Reset to default 4As the warnings suggest, please do the following:
- Rename the data array from
results
toproducts
since you are referencing it by the latter one as a name during render. - Make your data option a function returning an object since data option must be a function, so that each instance can maintain an independent copy of the returned data object. Have a look at the docs on this.
Vue.ponent('products', {
data() {
return {
products: []
}
},
mounted() {
axios
.get("js/prods.json")
.then(response => {
this.products = response.data.products;
});
},
template: `
//...
`
}
<div id="products">
<div class="productsItemContainer" v-for="product in products">
<div class="productsItem">
...
Also, since you're not using CDN (I think), I would suggest making the template a ponent with a separate Vue file rather than doing it inside template literals, something like that:
Products.vue
<template>
<div id="products">
<div class="productsItemContainer" v-for="product in products">
<div class="productsItem">
<!-- The rest of the elements -->
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Products',
data() {
return {
products: []
}
},
mounted() {
axios
.get("js/prods.json")
.then(response => {
this.products = response.data.products;
});
}
}
</script>
And then in your main JS file or anywhere else requiring this ponent:
import Products from './ponents/Products.vue';
new Vue({
el: '#app',
data() {
return {
//...
}
},
ponents: {
Products
}
})
<div id="app">
<Products />
</div>