emitting data from chiled to parent using vue.js and laravel - javascript

i new in vue.js i have test component is child and showdata component is parent my proplem is when i emit data from child to parent it is emitted successfully but when i show data in parent by #click="showusersdata1(listdata.id) i get empty data like attached image so how to show user data
here is my code
showdata.vue
<template>
<div>
id={{setUserData.id}},
name={{setUserData.name}}
email={{setUserData.email}}
<test v-on:showusersdata1="userData($event)"></test>
</div>
</template>
<script>
import MyHome from "./home";
// let Test=require('./components/test.vue').default
import test from "./test"
export default {
// components: {MyHome},
name: "showData",
data:function () {
return{
setUserData:{}
}
},
components:{
test
},
methods:{
userData:function (passedata) {
console.log(passedata)
// this.setUserData={}
this.setUserData= this.setUserData.push(passedata)
}
}
}
</script>
test.vue
<template>
<div class="row">
<div class="col-8">
<h1>this is test components1</h1>
<!-- List group -->
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username" aria-describedby="button-addon2">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-addon2">Button</button>
</div>
</div>
<div class="list-group" id="myList" role="tablist">
<a v-for ="(listdata,key) in list" class="list-group-item list-group-item-action active" data-toggle="list" href="#home" role="tab">
<ul class="test">
<i class="fas fa-trash" aria-hidden="true"></i>
<i class="fas fa-edit"></i>
<i #click="showusersdata1(listdata.id)" class="fas fa-eye"></i>
</ul> {{listdata.name}}</a>
</div>
</div>
<h1>this is cchiled show data coponent</h1>
</div>
</template>
<script>
import ShowData from "./showdata";
export default {
name: "Test",
components:{
ShowData
},
data: function () {
return {
list:{},
errors:{},
}
},
mounted(){
axios.post('/getAllData')
// .then((response) =>this.list=response.data )
.then((response) =>{
this.list=response.data
} )
.catch((error) =>this.errors=error.response.data.errors )
},
methods:{
showusersdata1:function (key) {
var index = this.list.find( ({ id }) => id == key );
this.$emit('userData', index)
}
}
}
</script>
<style scoped>
.test{
float:right
}
</style>

You are emiting here:
this.$emit('userData', index)
Which means the name of your event is 'userData'. That's what you have to listen to in the parent. But if you check your parent, you are listening to the event like this:
v-on:showusersdata1="userData($event)"
This means you are trying to listen to the 'showusersdata1' event, which is not fired. You are confusing the method name in your child for your event name. Instead of what you did, you can listen to your event like this:
v-on:userData="userData"
It's also kind of a convention to name event listeners by adding "on" in front of them, example:
event name is 'userDataReceived'
event listener would be onUserDataReceived

Related

Cannot receive event from child component vue3.0

I have a button component which is a child component
<template>
<div class="button-container">
<el-button #click="$emit('onClick')" type="primary">{{ text }}</el-button>
</div>
</template>
I want to emit the click event in order for parent component to receive.
Here is the parent component
<script>
import Button from "#/components/Button.vue";
export default {
components: { Button } ,
methods: {
toRegister() { this.$router.push('/register'); }
}
}
</script>
<template>
<Button #on-click="toRegister" text="Register here" textColor="#5fb878" textSize="8px"></Button>
</template>
But i don't receive any thing from here.
I thought the problem is on the event name, but after i changed the name from onClick to clicked, same problem still.
Try to rename your custom component from Button to something else :
const { ref } = Vue
const app = Vue.createApp({
methods: {
toRegister() {
console.log('clicked')
//this.$router.push('/register');
}
}
})
app.component('btn', {
template: `
<div class="button-container">
<button #click="$emit('onClick')" type="primary">text</button>
</div>
`
})
app.mount('#demo')
<script src="https://cdn.jsdelivr.net/npm/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<btn #on-click="toRegister" text="Register here" textColor="#5fb878" textSize="8px"></btn>
</div>

medium-zoom pagination issues

In my project I use medium-zoom with pagination. On first page it works well but on second, third, fourth... I have to click several times for close image...on second page...two times, on third 3 times...
it seems to be a problem with maybe any index number?
Here is my code:
<template>
<div>
<div v-if="loading" class="text-center">
<i class="fas fa-spinner fa-pulse fa-5x"></i>
</div>
<div v-else>
<div v-for="(item, imageIndex) in pageOfItems" :key="item.id" class="m-3">
<div class="row mt-3">
<div class="col-lg-9 my-auto" v-html="item.mytext"></div>
<div class="col-lg-3 my-auto text-center">
<article class="container">
<img
class="img-thumbnail"
:src="'http://localhost:4000/api/galeria/' + item.galeriaId + '_f.jpg'"
/>
</article>
</div>
</div>
<hr class="hr1" />
</div>
</div>
<div class="pb-0 pt-3 text-center">
<jw-pagination :items="info" :page-size="10" #changePage="onChangePage"></jw-pagination>
</div>
</div>
</template>
<script>
import mediumZoom from 'medium-zoom'
import axios from 'axios'
export default {
data() {
return {
info: [],
customLabels,
pageOfItems: [],
loading: true,
}
},
mounted() {
axios
.get('http://localhost:4000/api/fetch_galeria.php/')
.then((response) => (this.info = response.data))
.finally(() => (this.loading = false))
},
updated() {
mediumZoom('article img', {
background: 'transparent',
})
},
methods: {
onChangePage(pageOfItems) {
// update page of items
this.pageOfItems = pageOfItems
},
},
}
</script>
You will pretty much need to detach the event listeners here. Because it should be a lot of them added everytime due to the updated hook.
A naive implementation would be to add mediumZoom on the mounted hook. And when you do have a new changePage event, to detach it from all the images, then to apply it to the new ones with the same mediumZoom call.
Below is a way to see which event listeners (and probably how many) you have linked to a specific VueJS component. Select it in the Vue devtools and then, you will have access to the element's properties via $vm0.

Sort a precedently renderized and matched list with a v-for with a dropdown menu

I have this problem:
I render a list obtained by an API call with a v-for, and if you write into a form, only the elements that match the key written into the form are showed
Now, I need to sort this elements by name and by price too using a dropdown with buttons
is it possible?
Sorry for the external link, but I have some trouble pasting code into StackOverflow, maybe due the vue-boostrap
HTML part
code part
<div>
<b-dropdown id="dropdown-1" text="Dropdown Button" class="m-md-2">
<b-dropdown-item>Default Sort</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-item #click="sortByName">Sort by Name</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-item>Sot by Price</b-dropdown-item>
</b-dropdown>
</div>
<div class="d-flex flex-wrap justify-content-center">
<div class="card" v-for="product in filteredCatalogue" :key="product.id">
<img class="product pimage" :src="product.images.small" />
<hr class="product black-line" />
<h5 class="product name text-uppercase">{{product.name}}</h5>
<h5 class="product short-description">{{product.descriptions.short}}</h5>
<h5
class="product price"
v-if="product.price.currency_symbol=='€'"
>€ {{product.price.sell}}</h5>
<b-button id="button-shop" squared variant="warning">
<i class="fas fa-shopping-cart"></i>
<div id="yellow-button-text">ADD TO CART</div>
</b-button>
</div>
</div>
<form class="form-inline justify-content-center">
<div class="form-group">
<input
class="form-control bg-white border border-secondary"
type="text"
v-model="key"
placeholder="Cerca tra i prodotti"
value
autocomplete="off"
/>
</div>
</form>
import axios from "axios";
import { cacheAdapterEnhancer } from "axios-extensions";
export default {
data() {
return {
catalogue: [],
key: ""
};
},
created() {
axios
.get(
API_URL,
cacheAdapterEnhancer
)
.then(response => {
this.catalogue = response.data;
console.log(this.catalogue);
})
.catch(error => console.log(error));
},
computed: {
filteredCatalogue: function() {
return this.catalogue.filter(product => {
return product.name.toLowerCase().match(this.key.toLowerCase());
});
}
}
};
Check sort method on JavaScrtipt array here.

VueJS: Run function in parent component when event triggered in child component

This is my first proper Vue JS project...I've searched Stack O and can't find anything that specifically addresses my issue, but I apologise if this has already been asked.
The Problem
I have two components, the parent is the page layout, while the child is a module of that page. When somebody clicks on a button in the child component, I want to trigger a function in the parent component.
The $emit part of the process is firing correctly according to the VueJS Dev Tools, but the function in the parent doesn't trigger.
Where am I going wrong?
Here is my abberviated code (I've removed anything not related to the issue)...
Parent Component
<template>
<div :toggle-nav="showHideNav" :class="navState">
<div class="wrapper">
<layout-toolbar></layout-toolbar>
</div>
</div>
</template>
<script>
import layoutToolbar from '~/components/layout/toolbar.vue'
export default {
components: {
layoutToolbar,
},
data: function() {
return {
navState: 'menu-closed'
}
},
methods: {
showHideNav: function(event) {
if (this.navState == 'menu-closed') {
this.navState = 'menu-open'
} else {
this.navState = 'menu-closed'
}
}
}
}
</script>
Child Component
<template>
<div class="toolbar" role="navigation">
<div class="tools" role="group">
<button
class="button-icon"
aria-label="Open Navigation"
#click="$emit('toggle-nav')">
<i aria-hidden="true" class="far fa-bars" title="Open Navigation"></i>
<span class="sr-only">Open Navigation</span>
</button>
</div>
</div>
</template>
Do I need to be making use of props?
Appreciate any help that can be offered.
You have to pass a function as a prop and then emit that function from your child component. So your parent template looks like this .
<template>
<div :toggle-nav="showHideNav" :class="navState">
<div class="wrapper">
<layout-toolbar #showHideNav="showHideNav"></layout-toolbar>
</div>
</div>
</template>
And your child template looks like this
<template>
<div class="toolbar" role="navigation">
<div class="tools" role="group">
<button
class="button-icon"
aria-label="Open Navigation"
#click="$emit('showHideNav',<pass-your-event-or-data>)">
<i aria-hidden="true" class="far fa-bars" title="Open Navigation"></i>
<span class="sr-only">Open Navigation</span>
</button>
</div>
</div>
</template>

Display data when click on button with Meteor

I have one button, when I click I want to display data only if the value of the checkbox is true, If it false, it's display when DOM is created
But I can't please look my code.
Template.students.helpers({
all_students: () => {
return students.find();
}
});
Template.body.onCreated(() => {
Meteor.subscribe('students');
});
Template.students.events({
'submit .insert': (e) => {
e.preventDefault();
students.insert({
name: e.target[0].value,
age: e.target[1].value,
check: false
});
this._checkValue(e);
},
'click .is-delete': (e) => {
students.remove(e.currentTarget.id);
},
'click .check-checkbox': (e) => {
students.update(e.currentTarget.id, {
$set: {
check: !this.check
}
})
},
'click .all': () => {
// HERE
}
})
<template name="students">
<div class="content menu">
<ul>
<button class="ui button all">All list</button> <!-- THIS BUTTON -->
{{#each all_students}}
<li class="content-list" id="{{ _id }}">
<div class="name">{{ name }}</div>
<div class="age">{{ age }} ans</div>
<span id="{{ _id }}" class="delete is-delete"></span>
<div class="ui checkbox">
<input id="{{ _id }}" class="check-checkbox" type="checkbox" name="check">
</div>
</li>
{{/each}}
</ul>
</div>
</template>
Inside of my event handler click .all if I try to return students.find() it doesn't work.
The easiest way is to use a ReactiveVar to flag if the list should show like so:
Add the ReactiveVar to your template instance
Template.students.onCreated(() => {
this.showAllStudents = new ReactiveVar(false);
this.subscribe('students');
});
Then expose it with a helper:
Template.students.helpers({
showStudents() {
Template.instance().showAllStudents.get();
},
all_students() {
students.find();
};
});
In your template, test for the flag
<template name="students">
<div class="content menu">
<ul>
<button class="ui button all">All list</button> <!-- THIS BUTTON -->
{{#if showStudents}}
{{#each all_students}}
<li class="content-list" id="{{ _id }}">
<div class="name">{{ name }}</div>
<div class="age">{{ age }} ans</div>
<span id="{{ _id }}" class="delete is-delete"></span>
<div class="ui checkbox">
<input id="{{ _id }}" class="check-checkbox" type="checkbox" name="check">
</div>
</li>
{{/each}}
{{/if}}
</ul>
</div>
</template>
And add the event handler which just switches the state (ie. set opposite of current state):
Template.students.events({
'click .all': (event, instance) => {
instance.showAllStudents.set(!instance.showAllStudents.get());
}
})
If you haven't already got it, run meteor add reactive-var to get the package.
And if you're using imports, use import { ReactiveVar } from 'meteor/reactive-var'; to import it.

Categories