Programmatically append existing component to existing v-model in VueJS - vuejs2

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

Related

Property "id" was accessed during render but is not defined on instance & typeof id is undefined

When I click on the button I get this error up on the console
Uncaught (in promise) Error: Missing required param "id"
I'm trying to target the client based on its id from the URL.
This is the list of Clients!
<template>
<div class="page-clients">
<div class="columns is-multiline">
<div class="column is-12">
<h1 class="title">Clients</h1>
<router-link :to="{ name: 'AddClient' }" class="button is-light mt-4">Add Clients</router-link>
</div>
<div class="column is-3" v-for="client in clients" v-bind:key="client.id">
<div class="box">
<h3 class="is-size-4 mb-4">{{ client.name }}</h3>
<router-link v-if="typeof id !== 'undefined'"
v-bind:to="{ name: 'ClientView', params: { id: client.id } }" class="button is-light">Details
</router-link>
</div>
</div>
</div>
</div>
</template
This is the ClientView, from where a user can edit the client, but it isn't displaying at all!
<div class="page-client">
<div class="columns is-multiline">
<div class="column is-12">
<h1 class="title">{{ client.name }}</h1>
<router-link :to="{ name: 'EditClient', params: { id: client.id } }" class="button is-light mt-4">
Edit
</router-link>
</div>
<div class="column is-12">
<h2 class="subtitle">Contact details</h2>
<p><strong>{{ client.name }}</strong></p>
<p v-if="client.address1">{{ client.address1 }}</p>
<p v-if="client.address2">{{ client.address2 }}</p>
<p v-if="client.zipcode || client.place">{{ client.zipcode }} {{ client.place }}</p>
<p v-if="client.country">{{ client.country }}</p>
</div>
</div>
</div>
Here is my route!
{
path: "/dashboard/clients/:id",
name: "Client",
component: Client,
meta: {
requireLogin: true,
},
You could get access to the url parameters using $route.params which is return from a computed property :
computed:{
id(){
return this.$route.params.id
}
}
<router-link v-if="id !== undefined"

Cannot display data from an API using v-for in vuejs

I cannot get or display data from an API but the API is working fine and when I click the button, the data appears,
I want it to appear automatically
I'm using Axios method to connect to my API
I'm new to Vue.js and this is my simple code
var Ve = new Vue({
el: "#app",
data: {
products: [],
},
methods: {
getData: function(){
axios.get('http://localhost:8000/api/products')
.then(data => this.products = data.data)
.catch(err => console.log(err));
}
},
})
THIS IS WHERE I WANT TO DISPLAY MY DATA
<div class="col-sm-9 padding-right" id="app" >
<div class="features_items"><!--features_items-->
<h2 class="title text-center">المنتجات</h2>
<div class="col-sm-4" v-for="item in products">
<div class="product-image-wrapper">
<div class="single-products">
<div class="productinfo text-center">
<img src="images/products/2.jpeg" alt="" />
<h2>${{ item.price }}</h2>
<p>{{ item.name }}</p>
<i class="fa fa-shopping-cart"></i>أضف إلى السلة
</div>
<div class="product-overlay">
<div class="overlay-content">
<h2>${{ item.price }}</h2>
<p>{{ item.name }}</p>
<i class="fa fa-shopping-cart"></i>أضف إلى السلة
</div>
</div>
</div>
<div class="choose">
<ul class="nav nav-pills nav-justified">
<li><i class="fa fa-plus-square"></i>أضف إلى المفضلة</li>
</ul>
</div>
</div>
</div>
</div><!--features_items-->
<button type="button" #click="getData()">show</button>
</div>
I want it to appear automatically I'm using Axios method to connect to my API
As per my understanding, You want to bind the API data on component load. If Yes, You can call getData() method in the mounted() life cycle hook.
mounted hook used to run code after the component has finished the initial rendering and created the DOM nodes.
Demo :
var vm = new Vue({
el:"#app",
data: {
products: [],
},
mounted() {
this.getData();
},
methods: {
getData() {
// Here make an API call and bind the response in products.
this.products = [{
name: 'product1',
price: 50
}, {
name: 'product2',
price: 100
}, {
name: 'product3',
price: 150
}, {
name: 'product4',
price: 200
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="(item, index) in products" :key="index">{{ item.name }} - {{ item.price }}</li>
</ul>
</div>

Cannot read property 'forEach' of undefined VueJS Firebase

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

vuex unknown action type: addToCart

hello everyone im trying to add product into cart array so i can render it after , i used vuex but i got this error : Console was cleared
[vuex] unknown action type: addToCart
hopefully u can give me some hint so i can fix this issue
thank you so much !!
here is the sandbox : https://codesandbox.io/s/suspicious-minsky-9cig7?file=/src/components/Products.vue
<template>
<main>
<div class="margin"></div>
<div class="shopTitle">
<h1>Shop</h1>
</div>
<section class="categoriesSection">
<ul class="categories">
<li>
See All
</li>
<li>
Shoes
</li>
<li>
Suits
</li>
</ul>
</section>
<section>
<div class="products">
<div class="product" v-for="product in filteredProducts" :key="product.productId">
<div class="imgproduct"></div>
<div class="productDetails">
<div>
<h1>{{product.productTitle}}</h1>
</div>
<div>
<i onClickButton class="fa fa-heart"></i>
</div>
<div>
<p>{{product.productPrice}}</p>
</div>
<div>
<i onClickButton #click="addToCart(product)" class="fa fa-shopping-cart"></i>
</div>
</div>
</div>
</div>
</section>
</main>
</template>
<script>
export default {
data() {
return {};
},
computed: {
selectedCategory: {
// getter
get: function() {
return this.$store.getters.selectedCategory;
},
// setter
set: function(newValue) {
return this.$store.commit("updateCategory", newValue);
}
},
filteredProducts() {
return this.$store.getters.filteredProducts;
}
},
methods: {
addToCart: function(product) {
this.$store.dispatch("addToCart", product);
}
}
};
</script>
You have a mutation called addToCart but no action either create an action called addToCart or just call the mutation directly :
this.$store.commit("addToCart", product);

Vue 2.x authentication links not hiding until page refresh

I am new to Vue and created a basic authentication application.
AuthService.js
module.exports = {
isLoggedIn: function() {
if (localStorage.getItem("authUser") != null) {
return true;
} else {
return false;
}
},
Logout: function() {
localStorage.removeItem("authUser");
},
}
App.vue
<template>
<div id="app" >
<top-progress ref="topProgress"></top-progress>
<div class="nav is-light is-fixed-top">
<div class="container">
<span class="nav-toggle" v-on:click="toggleNav" v-bind:class="{ 'is-active': isActive }">
<span></span>
<span></span>
<span></span>
</span>
<div class="nav-right nav-menu" v-bind:class="{ 'is-active': isActive }">
<router-link v-ripple to="/" class="nav-item r-item"><i class="fa fa-home"></i>Home</router-link>
<router-link v-ripple to="faq" class="nav-item r-item"><i class="fa fa-file"></i>Features</router-link>
<router-link v-ripple to="dashboard" class="nav-item r-item"><i class="fa fa-dashcube"></i>Dashboard</router-link>
<router-link v-ripple to="faq" class="nav-item r-item"><i class="fa fa-quora"></i>Faq</router-link>
<a class="nav-item r-item" v-if="LoggedIn"><i class="fa fa-sign-out" #click.prevent="Logout"></i>Logout</a>
<div class="nav-item" v-if="!LoggedIn">
<p class="control">
<router-link to="login" class="button is-primary is-outlined">
<span class="icon">
<i class="fa fa-download"></i>
</span>
<span> Join Now</span>
</router-link>
</p>
</div>
</div>
</div>
</div>
<br>
<router-view></router-view>
<footer class="footer is-secondary">
<div class="container">
<div class="columns">
<div class="column">
<p>And this right here is a spiffy footer, where you can put stuff.</p>
</div>
<div class="column has-text-right">
<a class="icon" href="#"><i class="fa fa-facebook"></i></a>
<a class="icon" href="#"><i class="fa fa-twitter"></i></a>
</div>
</div>
</div>
</footer>
</div>
</template>
<script>
import {isLoggedIn,Logout} from "./service"
import miniToastr from 'mini-toastr'
import topProgress from 'vue-top-progress'
export default {
name: 'app',
components:{topProgress},
data:function(){
return {
isActive:false,
LoggedIn:false,
}
},
created(){
this.LoggedIn=isLoggedIn();
},
mounted(){
miniToastr.init()
this.$refs.topProgress.start()
setTimeout(() => {
this.$refs.topProgress.done()
}, 2000)
},
methods:{
Logout:function(){
Logout();
this.$router.push("login");
},
}
}
</script>
<style lang="sass">
..//
</style>
After successful login, I am using this.$router.push("home") to navigate to home component but the Login/Logout button not hiding/showing until I refresh the page.
The problem you are having is the created: hook is only called when App.vue is first created. Since this component holders the router-view it is always there as you move around the app — it's never destroyed, so it never needs to be created again. As a result your this.LoggedIn is only updated when you first load the app (or as you discovered, hit refresh).
You need to find a different way to update this.LoggedIn. One obvious possibility it to set it in the logih/logout methods.
Logout:function(){
Logout();
this.LoggedIn = isLoggedIn(); // or simply this.LoggedIn = false
this.$router.push("login");
},
It looks like users will login in a different component, so you will need to send an event from the child component to App.vue and trigger a method on App.vue to set this.LoggedIn when users login.
There are probably other possibilities that will come to mind now that you see why it isn't working.