I have a Vue component called Shoes, which utilizes the Products component that in turn uses the Product component. The Products component receives an array from an API to populate the Product component with information.
However, when I attempt to fetch an array from the API within the Shoes component and pass it to the Products component (which expects an Array), Vue throws an error saying it received Undefined. What's going on...
"Shoes" component:
<!-- eslint-disable-next-line -->
<template>
<div>
<app-products :new_products="new_products" :old_products="old_products"></app-products>
</div>
</template>
<script>
import getData from "../data/get_data";
export default {
data() {
return {
}
},
methods: {
async getShoes () {
const response = await getData('products', 'shoes');
const new_products = [],
old_products = [];
for (const product of response.data)
product.tag === 'new' ? new_products.push(product) : old_products.push(product);
console.log(this.products.new, this.products.old);
this.new_products = new_products;
this.old_products = old_products;
console.log(this.products.new, this.products.old);
}
},
async mounted() {
await this.getShoes()
}
}
</script>
<style>
</style>
Products component:
<template>
<div>
<div class="wrap wrap_for_new" v-if="new_products.length !== 0">
<h1 class="write" >These items are now available!</h1>
<div class="main_wrap">
<app-product v-for="(product, key) of new_products" class="new_product" :key="key" :name="product.name" :descriptions="product.description" :price="product.price" :ImageId="product.id" :count="product.count"></app-product>
</div>
</div>
<div class="wrap" v-if="old_products.length !== 0">
<div class="main_wrap">
<app-product v-for="(product, key) of old_products" :key="key" :name="product.name" :descriptions="product.description" :price="product.price" :ImageId="product.id" :count="product.count"></app-product>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
new_products: {
type: Array,
required: true
},
old_products: {
type: Array,
required: true
}
},
methods: {
setGridColumns() {
let ret_ = '';
for (let i = 0; i < Math.round(window.innerWidth / 170); i++) {
ret_ += '1fr ';
}
for (let el of document.querySelectorAll('.main_wrap')) el.style.gridTemplateColumns = ret_;
},
},
async beforeCreate() {
console.log(this.new_products, this.old_products);
this.setGridColumns();
}
}
</script>
<style>
.wrap_for_new {
margin-top: 50px;
}
.wrap {
border-bottom: 1px solid red;
}
.main_wrap {
position: relative;
display: grid;
height: 100%;
grid-template-rows: 1fr;
grid-gap: 5px;
}
.new_product {
border: red solid 1px !important;
}
.write {
text-align: center;
font-size: 150%;
}
.red {
color: red;
}
.write span {
color: red;
}
</style>
Product component:
<template>
<div class="product" >
<div class="look" @click="look">
View
</div>
<img :src="`localhost:8000/image/${ImageId}`" class="image_still" :alt="`${name} product image`"/>
<div class="product_name"> {{ name }} </div>
<div class="descriptions">{{descriptions | toolongtext}}</div>
<div class="price"> {{price}} </div>
<div class="count"> {{count}} items </div>
</div>
</template>
<script>
import { animate } from '../staticFunctions/animate';
import emitter from "../../src/main";
export default {
props: {
name: String,
descriptions: String,
price: String,
ImageId: String,
count: Number
},
methods: {
look() {
emitter.$emit('look', {
name: this.name,
descriptions: this.descriptions,
price: this.price,
ImageId: this.ImageId,
count: this.count
});
animate('product-look', false);
this.isOpened = !this.isOpened;
}
},
filters: {
toolongtext: value => value.length > 51 ? value.slice(0, 51) + '...' : value
}
}
</script>
<style scoped>
.product {
height: 400px;
width: 90%;
background-color: #fafafa;
box-shadow: 0 0 5px gray;
margin: 10px;
border-radius: 10px;
float: left;
max-width: 90vw;
max-height: 90vw;
display: grid;
grid-template-rows: 0.5fr 4fr 1fr 2fr 1fr;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"look look"
"img img"
"name name"
"desc desc"
"prc count";
}
.look {
opacity: 0;
width: 100%;
text-align: center;
grid-area: look;
transition: opacity 1s;
}
.product:hover .look,
.product:active .look {
opacity: 0.6;
}
.product * {
text-align: center;
}
.descriptions {
grid-area: desc;
}
.image_still {
grid-area: img;
}
.product_name {
grid-area: name;
}
.price {
grid-area: prc;
}
.count {
grid-area: count;
}
</style>