How to share data between two component in vuejs with Event Bus - javascript

I am trying to implement a global event bus in order to send a variable from component A to component B.
Here is the component A code:
data () {
return {
commandes: [],
}
},
envoyer() {
this.$eventBus.$emit('commande', this.commandes);
},
Here is the component B code:
<template>
<div class="container">
<div class="row justify-content-center">
<!-- Table row -->
<div class="row">
<div class="col-12 table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Qté</th>
<th>Produit</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
<tr v-for="(commande, index) in commandes" :key="index">
<td>{{ commande.quantite }}</td>
<td>{{ commande.produit_id }}</td>
<td>{{ commande.montant }}</td>
</tr>
</tbody>
</table>
</div>
<!-- /.col -->
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
commande: [],
}
},
methods: {
},
mounted() {
this.$eventBus.$on('commande', (commandes) => {
this.commande = commandes;
console.log(commandes);
})
}
}
</script>
I'm getting this error when component B is displayed:
[Vue warn]: Property or method "commandes" is not defined on the instance but referenced during render.
How to solve this?

In your template you are referencing commandes
<tr v-for="(commande, index) in commandes" :key="index">
but your data doesn't return it, it returns commande
data() {
return {
commande: [],
}
}
Update your data and bus listeners:
data() {
return {
commandes: [],
}
}
...
this.$eventBus.$on('commande', (commandes) => {
this.commandes = commandes;
console.log(commandes);
})

Related

Uncaught (in promise) TypeError: Cannot use 'in' operator to search for 'path' in undefined

I am a new learner. I am trying to add cart feature using vue. Here is my view name Cart.vue for the cart.
<template>
<div class="page-cart">
<div class="columns is-multiline">
<div class="column is-12">
<h1 class="title">Cart</h1>
</div>
<div class="column is-12 box">
<table class="table is-fullwidth" v-if="cartTotalLength">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<th></th>
</tr>
</thead>
<tbody>
<CartItem
v-for="item in cart.items"
v-bind:key="item.product.id"
v-bind:initialItem="item" />
</tbody>
</table>
<p v-else>You don't have any products in your cart...</p>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import CartItem from '#/components/CartItem.vue'
export default {
name: 'Cart',
components: {
CartItem
},
data() {
return {
cart: {
items: []
}
}
},
mounted() {
this.cart = this.$store.state.cart
},
computed: {
cartTotalLength() {
return this.cart.items.reduce((acc, curVal) => {
return acc += curVal.quantity
}, 0)
},
}
}
</script>
This is the CartItem.vue component that I used:
<template>
<tr>
<td><router-link :to="item.product.get_absolute_url">{{ item.product.name }}</router-link></td>
<td>Rs {{ item.product.price }}</td>
<td>
{{ item.quantity }}
</td>
<td>Rs {{ getItemTotal(item).toFixed(2) }}</td>
<td><button class="delete"></button></td>
</tr>
</template>
<script>
export default {
name: 'CartItem',
props: {
initialItem: Object
},
data() {
return {
item: this.initialItem
}
},
methods: {
getItemTotal(item) {
return item.quantity * item.product.price
}
},
}
</script>
I cannot see any product and the related values in the cart. I am getting this error -
Uncaught (in promise) TypeError: Cannot use 'in' operator to search for 'path' in undefined.
I am unable to find out the mistake in my code. Please help me out. When I am removing the component from the cart.vue, then the error gets eliminated. But I need that component.

Vue 3 sorting - this.lists.sort is not a function

Vue 3 front-end template:
<template>
<div class="container">
<router-link to="/user/create" class="btn btn-success mt-5 mb-5">Add New</router-link>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<button #click="sortBy('email')">Sort by email</button>
<button #click="sortBy('username')">Sort by Name</button>
<tr v-for="(item, index) in lists" :key="index">
<td scope="row">{{ index }}</td>
<td>{{ item.username}}</td>
<td>{{ item.email}}</td>
My method for sorting.
data() {
return {
lists: [], //filled in firebase by /get route
};
methods: {
sortBy(prop) {
this.lists.sort((a,b) => a[prop] < b[prop] ? -1 : 1)
},
When i try to click on a sort button by email or username i'm receiving the error sorts is not a functions.
You forgot to close the braces you opened for data() {}
data() {
return {
lists: [], //filled in firebase by /get route
};
},
methods: {
sortBy(prop) {
this.lists.sort((a,b) => a[prop] < b[prop] ? -1 : 1)
},

not able to vue pass props to component's data

I am trying to pass the props in my component to the same component's data object. However, I am only getting null. Can anyone advise how I should approach this? It seems that my vue component is not able to get the props on initial rendering/load.
const teamInformationTemplate = {
template:
`
<div class="col-lg-6 col-md-12">
<div class="card card">
<!---->
<div class="card-header">
<h6 class="title">
TEAMS
</h6>
<br>
<select id="select_model_version" #change="get_team_information($event.target.value)" class="form-control form-control-sm form-group col-md-4">
<option v-for="team in teams" :value="team.team_id" :key="" :id="team.team_id">
{{ team.team_name }}
</option>
</select>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table tablesorter">
<thead class="text-primary">
<tr>
<th>#</th>
<th>Name</th>
</tr>
</thead>
<tbody class="">
<tr v-if="team_members!=null" v-for="(member, index) in team_members">
<td>{{index+1}}</td>
<td>{{member.firstname}}
</tr>
</tbody>
</table>
</div>
<!---->
<!---->
</div>
</div>
</div>
`,
props: ['teams', 'team_members', 'team_name'],
data() {
return {
template_teams : this.teams,
template_team_name : this.team_members,
template_team_members : this.team_name,
}
},
methods: {
get_team_information : function (team_id) {
$.post(js_local.ajaxurl, {
action: 'abcdefg',
team_id: team_id
}).done((data) => {
let parsed_data = JSON.parse(data)
}).fail(function (data) {
console.log('fail # { action : get_team_information }', data)
})
}
}
}
Try to initialize them inside the updated hook as follows:
data() {
return {
template_teams: [],
template_team_name: [],
template_team_members: [],
}
},
updated() {
this.template_teams = this.teams;
this.template_team_name = this.team_members;
this.template_team_members = this.team_name;
}

Vue.js data table only showing data in first column

I am trying to iterate through an object, pulled from database using axios. I am able to make the object show up in my data table, but i am unable to make it break the data to the specified columns
first snippet is the parent component. the tr and td for the actual list i broke out to a separate component but that may need to be fixed.
<template>
<div class="container">
<router-link to="/add" class="btn btn-primary btn-sm float-
right">AddClient</router-link>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Type</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th></th>
</tr>
</thead>
<client-info></client-info>
</table>
</div>
</template>
<script>
import ClientInfo from '#/components/clientslistexperience/ClientInfo'
export default {
name: 'ClientsList',
components: {
ClientInfo
},
methods: {
},
}
</script>
enter code here
next is the component iterating through the data to be show in the table
<template>
<div class="client-info">
<tbody>
<tr v-for="(client, index) in clients" v-bind:key="index"
:client="client">
<th scope="row">{{ client.id }}</th>
<td>{{ client.name }}</td>
<td>{{ client.type }}</td>
<td>{{ client.email }}</td>
<td>{{ client.phone }}</td>
</tr>
</tbody>
</div>
import { mapState } from 'vuex'
export default {
name: 'client-info',
props: {
id: Array,
type: String,
name: String,
email: String,
phone: Number,
},
computed: {
...mapState ([
'clients'
])
},
created() {
this.$store.dispatch('retrieveClients')
}
}
</script>
enter code here
last is the vuex store where axios request is being made. now i know using the vuex for smaller projects is over kill but im intending for this to become rather large so this is the method ive chosen. any help would be awesome! Thanks.
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
axios.defaults.baseURL = 'http://client-api.test/api'
export default new Vuex.Store({
state: {
clients: []
},
mutations: {
retrieveClients(state, clients) {
state.clients = clients
},
},
actions: {
retrieveClients(context) {
axios.get('/clients')
.then(response => {
// console.log(response)
context.commit('retrieveClients', response.data)
})
.catch(error => {
console.log(error)
})
}
}
})
enter image description here
In fact, you need to remove the div root element in your ClientInfo.vue component.
Replace the div by tbody and it solve your problem ;)
<template>
<tbody class="client-info">
<tr v-for="(client, index) in clients"
:key="index">
<td>{{ client.id }}</td>
<td>{{ client.name }}</td>
<td>{{ client.type }}</td>
<td>{{ client.email }}</td>
<td>{{ client.phone }}</td>
</tr>
</tbody>
</template>
Full demo here > https://codesandbox.io/s/v8vw0z89r7

Vue.js 2 components parent child item not defined

I am new to vue and I am getting the error referenceError: items is not defined. Can anyone see why this happens or give me some pointers?
I think it has something to do with the items not being set on first look at the template.
My code:
<div id="root">
<task-list></task-list>
<template id="my-parent">
<table>
<thead>
<tr>
<th>Name</th>
<th>id</th>
</tr>
</thead>
<tbody>
<tr is="task" v-for="item in items" :item="item"></tr>
</tbody>
</table>
</template>
<template id="my-child">
<tr>
<td></td>
<td>{{ item.name }}</td>
<td>{{ item.id }}</td>
</tr>
</template>
</div>
<script>
Vue.component('task-list', {
template: '#my-parent',
data: function() {
return {
items: []
}
},
methods: {
getMyData: function(val) {
var _this = this;
$.ajax({
url: 'vuejson.php',
method: 'GET',
success: function (data) {
console.log(data);
_this.items = data;
},
error: function (error) {
alert(JSON.stringify(error));
}
})
}
},
mounted: function () {
this.getMyData("0");
}
});
Vue.component('task', {
template: '#my-child',
props: ['item'],
data: function() {
return {
item: {}
}
}
});
new Vue({
el: "#root",
});
</script>
Here is working modified code:
<template id="my-child">
<tr>
<td>{{ item.name }}</td>
<td>{{ item.id }}</td>
</tr>
</template>
<template id="my-parent">
<table>
<thead>
<tr>
<th>Name</th>
<th>id</th>
</tr>
</thead>
<tbody>
<tr is="task" v-for="item in items" :item="item"></tr>
</tbody>
</table>
</template>
<div id="root">
<task-list></task-list>
</div>
And js:
Vue.component('task-list', {
template: '#my-parent',
data: function() {
return {
items: []
}
},
methods: {
getMyData: function(val) {
var _this = this;
_this.items = [{name: '1.name', id: 1}];
}
},
mounted: function () {
this.getMyData("0");
}
});
Vue.component('task', {
template: '#my-child',
props: ['item'],
data: function() {
return {
}
}
});
new Vue({
el: "#root",
});
jsfiddle
It would be much easier to you to work with vue, if you do some tutorials first:)
edit:
And one more thing: if you declare property(item in your case), dont use that name in data.
So, what I did:
- placed templates outside of your root element
- removed "item" from data
You should describe templates outside div#root.
Example
<div id="root">
<task-list></task-list>
</div>
<template id="my-parent">
<table>
<thead>
<tr>
<th>Name</th>
<th>id</th>
</tr>
</thead>
<tbody>
<tr is="task" v-for="item in items" :item="item"></tr>
</tbody>
</table>
</template>
<template id="my-child">
<tr>
<td></td>
<td>{{ item.name }}</td>
<td>{{ item.id }}</td>
</tr>
</template>
Because if they are in #root they are part of vue instance for it, and there is no items in it.
new Vue({
el: "#root",
//no items
});

Categories