Cannot read property 'forEach' of undefined VueJS Firebase - vuejs2

I use the framework VueJS and the NoSQL Database Firebase.
Here I want to display the products' data. And particulary the images of the products stored in the Cloud Firestore in Firebase.
This is the HTML code :
<div class="col-md-4"v-for="(product, index) in products" :key="index">
<div class="card product-item">
<carousel :perPage="1">
<slide v-for="(image, index) in product.images" :key="index">
<img :src="image" class="card-img-top" alt="..." width="250px">
</slide>
</carousel>
<div class="card-body">
<div class="d-flex justify-content-between">
<h5 class="card-title">{{ product.name }}</h5>
<h5 class="card-prices">{{ product.price }} €</h5>
</div>
<button class="btn btn-primary mx-3 butn" >
Add to cart
</button>
</div>
</div>
</div>
and the js script :
<script>
import {db} from '../../firebase';
export default {
name: "Productslist",
props: {
msg: String
},
data(){
return {
products: [],
}
},
firestore() {
return {
products: db.collection("products")
}
}
},
};
</script>
It displays the products data like the name and the price but not the images. I have a Cannot read property 'forEach' of undefined.

Probably one of the products have images set to undefined
product.images = undefined

Related

Nuxt Props pass to data and set images

how do i pass props into data ? i have a object that pass into prop and i want prop to set the image url with data "mainImage", must keep the mainImage.
<template>
<!-- start Product Header -->
<div class="ps-product__header">
<div class="ps-product__thumbnail" data-vertical="false">
<div class="ps-wrapper">
<div class="ps-product__gallery">
<div class="col-12 px-md-2 d-none d-md-block">
<div class="" style="cursor: pointer">
<b-img :src="mainImage" alt="" style="width: 100%" class="image" #click="showMainImage()"></b-img>
</div>
</div>
</div>
</div>
<div class="ps-product__variants">
<div class="col-12 d-none d-md-block my-4">
<div class="row">
<div class="col-3" v-for="(image, index) in product.images" :key="index">
<div class="thumbnail" style="cursor: pointer" #click="changeMainImage(image.src)">
<b-img :src="`${image.src}`" style="width: 100%" alt="" class="image" :class="mainImage === image ? 'activess' : ''"></b-img>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
here is the script
<script>
export default {
name: 'ShopHeader',
props: {
product: {
type: Object,
required: true
}
},
data() {
return {
mainImage: String,
}
},
methods: {
changeMainImage(image) {
this.mainImage = image
}
},
mounted() {
this.mainImage = this.product.image
console.log(this.mainImage)
}
}
</script>
sample : https://stackblitz.com/edit/nuxt-starter-pake3o?file=components%2FShopHeader.vue
when you type on the stackblitz url with /product, the image will show up but when you go through the link the image wont show up, so anyone know how to fix this problem ? i assume it was mounted only load once and component wont render after it.
add v-if to tag
<img v-if="mainImage" :src="mainImage" class="image">

Pagination in vue.js framework

Error with Pagination in vue.js framework in view page, The Pagination bar is working fine but I have 50 records on the same page. The Pagination bar is 17 => 50/3 . The Post is displayed in div section not in Table.
<template>
<div class="blog">
<h2>{{ pageDescreption }}</h2>
<hr />
<div class="alert alert-success" role="alert" v-text="alertTitel"></div>
<div class="row">
<div class="col-md-8">
<div class="posts-area">
<PostList
id="PostList"
v-for="post in posts"
:key="post.id"
:post="post"
:current-page="currentPage"
:per-page="perPage"
/>
<div class="overflow-auto">
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
aria-controls="PostList"
></b-pagination>
<p class="mt-3">Current Page: {{ currentPage }}</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import PostList from "#/components/Blogs/PostList.vue";
import PostJson from "../Gatewaye/post.json";
export default {
data: function() {
return {
pageName: "blog",
pageDescreption: "This is an Blog page",
alertTitel: "List of all Posts",
posts: PostJson, // array of posts [50 records]
perPage: 3,
currentPage: 1
};
},
name: "Blog",
components: {
PostList
},
computed: {
rows() {
return this.posts.length;
}
}
};
</script>
And in Components file Blog.vue is:
<template>
<div class="PostList">
<div class="post-container text-left">
<span class="post-views badge badge-primary" title="Views">{{
post.views
}}</span>
<h3 class="post-title" title="Title">{{ post.title }}</h3>
<span class="post-date" title="Date">{{ post.date }}</span>
<p class="post-body">
{{ post.contant }}
</p>
<div class="row">
<div class="col-sm-6">
<span class="post-author" title="Auther">{{ post.auther }}</span>
</div>
<div class="col-sm-6 text-right">
<span class="post-category" title="Category">{{
post.category
}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["post"],
name: "PostList"
};
</script>
The Pagination bar is working fine but I have 50 records on the same page ... Thank you
Use a computed property to slice the post array in the parent component:
computed: {
paginatedposts() {
return this.posts.slice(this.perPage*(this.currentPage-1), (this.perPage*(this.currentPage-1))+this.perPage);
}
}
Now you just need to bind this computed property:
<PostList
id="PostList"
v-for="post in paginatedposts"
:key="post.id"
:post="post"
/>

Data not updating when API changed on Vue Js

Ok, I have a problem, here I make a data post with a tag, and when I click the tag the other data posts are not updated by the tag.
i'm get the api with created function, Do I have to use vuex?
can everyone help me, thanks very much
this is my template
<div class="col-md-4 mb-4" v-for="post in posts" :key="post.id">
<div class="card h-100 shadow-sm border-0 rounded-lg">
<div class="card-img">
<img :src="path+'/storage/posts/'+post.image" class="w-100"
style="height: 200px;object-fit: cover;border-top-left-radius: .3rem;border-top-right-radius: .3rem;">
</div>
<div class="card-body">
<router-link :to="{name: 'detail_post', params: {slug: post.slug}}"
class="text-dark text-decoration-none">
<h6>{{ post.title }}</h6>
</router-link>
</div>
<div class="card-footer bg-white">
<i class="fa fa-calendar" aria-hidden="true"></i> {{ post.created_at }}
</div>
</div>
</div>
this is my JavaScript
<script>
//import axios
import axios from 'axios'
export default {
name: 'PostIndex',
data() {
return {
path: axios.defaults.baseURL,
posts: []
}
},
created() {
//get post homepage
axios.get(`/api/tag/${this.$route.params.slug}`).then(response => {
this.posts = response.data.data.data;
})
}
}
</script>

How to update data() in vue.draggable

I know this may be basic stuff... but I cannot get my data updated when using Vue.Draggable 2.23. In the code below, the 4 lists are returned from the axios call exactly as they are now return by data(), but then, of course, with content. Somehow I keep getting "Property or method "lane0" is not defined on the instance but referenced during render." In App.vue:
<script>
import draggable from "vuedraggable";
import axios from "axios";
export default {
name: "two-lists",
display: "Two Lists",
order: 1,
components: {
draggable
},
data() {
return {
"lane0": [],
"lane1": [],
"lane2": [],
"lane3": []
}
},
mounted () {
axios
.get('http://localhost:8000/pylims/get_sequencable_lanes/10/S4')
.then(response => (this.data= response.data))
},
methods: {
log: function(evt) {
window.console.log(evt);
}
}
}
</script>
On request, the HTML part (template in App.vue):
<template>
<div class="row">
<div class="col-3">
<h3>Draggable 1</h3>
<draggable class="list-group" :list="lane0" group="people" #change="log">
<div
class="list-group-item"
v-for="(element, index) in lane0"
:key="element.sample_name"
>
{{ element.sample_name }} {{ index }}
</div>
</draggable>
</div>
<div class="col-3">
<h3>Draggable 2</h3>
<draggable class="list-group" :list="lane1" group="people" #change="log">
<div
class="list-group-item"
v-for="(element, index) in lane1"
:key="element.sample_name"
>
{{ element.sample_name }} {{ index }}
</div>
</draggable>
</div>
<div class="col-3">
<h3>Draggable 3</h3>
<draggable class="list-group" :list="lane2" group="people" #change="log">
<div
class="list-group-item"
v-for="(element, index) in lane2"
:key="element.sample_name"
>
{{ element.sample_name }} {{ index }}
</div>
</draggable>
</div>
<br><br>
{{ lane0 }}
<br><br>
{{ lane1 }}
<br><br>
{{ lane2 }}
<br><br>
{{ lane3 }}
</div>
</template>
As Tobias G. states in the comment and is clearly explained here: https://v2.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html the problem is solved by wrapping the lanes in an object, and then updating that from within the mounted() function, like this:
data() {
return {
lanes: {
"lane0": [],
"lane1": [],
"lane2": [],
"lane3": []
}
}
},
mounted () {
axios
.get('http://localhost:8000/pylims/get_sequencable_lanes/10/S4')
.then(response => (this.lanes = response.data))
},
then using it in the HTML part like this:
<draggable class="list-group" :list="lanes.lane0" group="people" #change="log">

Programmatically append existing component to existing v-model in VueJS

Like the title says, Im trying to append a vue-component to an existing v-model
The only thing i found on the internet was the v-for solution to add more elements, but that is not what I want to do since this v-model could have multiple components
chat.vue
The V-model im trying to append to
<template>
<ul class="chat-ul" v-model="messages">
<chat-entry :name="name" :message="text" direction="left"></chat-entry>
</ul>
</template>
Here is where im stuck, how i can add the components
<script>
Vue.component('chat-entry', require('./entry.vue'));
module.exports = {
data: function () {
return {
name: 'Default name',
message: 'Default message',
messages: null,
}
},
mounted: function () {
// This is the what i want to achive
this.messages.append('chat-entry', {direction: 'left', message: 'hello', name: 'HeatON'});
this.$http.get('/etc/yelp.xi').then(response => {
for (let q in response.body.arr) {
this.messages.append('chat-entry', {direction: 'left', message: q.message, name: q.name});
}
});
}
}
entry.vue
<template>
<div v-if="direction == 'left'">
<li>
<div class="message-data">
<span class="message-data-name"><i class="fa fa-circle you"></i> {{ name }}</span>
</div>
<div class="message you-message"> {{ message }} </div>
</li>
</div>
<div v-else>
<li class="clearfix">
<div class="message-data align-right">
<span class="message-data-name">{{ name }}</span> <i class="fa fa-circle me"></i>
</div>
<div class="message me-message float-right"> {{ message }} </div>
</li>
</div>
</li>
Is something like this even possible? if not, what is the proper approach?
Thanks in advance