Call function from parent template in vue.js - vuejs2

I have a button in parent component template like below.
<template>
<div class="data_table">
<button class="mini ui button" #click="show">
</div>
</template>
This show() is kept in child component like below
<script>
export default {
data:
function () {
return {
value: this.active1
}
},
props: {
active1: true
},
methods: {
show () {
this.active1 = true
}
},
}
</script>
How can I call that show() function ?
I am using vue-cli.
Thanks

Child Component
<template>
<div class="data_table">
<button class="mini ui button" #click="show">
</div>
</template>
data: => ({
value: this.active1
}),
props: {
active1: {
type: Boolean
}
},
methods: {
show () {
this.$emit('someEventName')
}
}
Parent Component
<template>
<child-component
:active1="booleanValue"
#someEventName="show"
/>
</template>
data: => ({
booleanValue: false
}),
method: {
show () {
this.booleanValue = true
}
}

Related

Vue: Register part of package as component

I have got a wrapper around a package called vue-awesome-swiper, as follows:
Slider.vue
<template>
<div class="media-slider">
<slot :sliderSetting="sliderSettings" :name="name">
<swiper :options="sliderSettings[name]"
class="swiper"
v-if="slides"
ref="default-slider">
<slot name="slides" :slides="slides" :code="code">
<swiper-slide v-for="image in slides" :key="image" v-if="endpoint"
:style="{'background-image': `url('${image}')`}">
</swiper-slide>
</slot>
<div class="swiper-button-next swiper-button-white" slot="button-next"></div>
<div class="swiper-button-prev swiper-button-white" slot="button-prev"></div>
<div class="swiper-pagination" slot="pagination"></div>
<div class="swiper-scrollbar" slot="scrollbar"></div>
</swiper>
</slot>
</div>
</template>
<script>
import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
import 'swiper/css/swiper.css';
import Axios from '../../../../axiosConfig';
// https://github.surmon.me/vue-awesome-swiper/
export default {
components: { Swiper, SwiperSlide },
data: function() {
return {
code: null,
images: [],
defaults: {
'default-slider': {
loop: true,
loopedSlides: 5,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
},
scrollbar: {
el: '.swiper-scrollbar',
hide: true
}
}
},
sliderSettings: {}
}
},
props: {
endpoint: {
type: String,
default: null
},
settings: {
type: Object,
default: {}
},
theme: {},
name: {},
hash: {},
numberOfImages: {},
imageFormat: {},
vehicleId: {}
},
computed: {
slides() {
if (this.images.length) {
return this.images;
}
return [...Array(parseInt(this.numberOfImages))].map(
(_, i) => {
i++;
return this.imageFormat.replace('#', i);
}
);
}
}
}
</script>
As you can see I have got a slot within this component, however it must use an instance of SwiperSlide for it to work. I need to register this as a component to use it.
However this isn't working as expected:
Vue.component('slider', () => import('./components/Media/Slider/Index'));
Vue.component('slide', () => import('vue-awesome-swiper'));
How can I do this?
Edit
<slider class="app">
<template v-slot:slides="props">
<slide :style="{'background-image': `url('img-src/${props.code}/theme/slide-1.jpg')`}"></slide>
</template>
</slider>
An import like this import() is gonna import the default export of the package, what you have done here is that you have destructured the import with import { .. } from ".." that means it has an named export.
However try it like this
Vue.component('slider', () => import('./components/Media/Slider/Index'));
Vue.component('slide', async () => (await import('vue-awesome-swiper')).SwiperSlide);

Access the variables of a component

I'd like to access a component variable. This variable is modified by an html input.
Here is my current code
Parent :
<template>
<component>Child</component>
</template>
<script>
export default {
data () {
return {
dataChild : '',
}
</script>
Child :
<template>
<input type="text" name="data" v-model="data" class="form-control">
</template>
<script>
export default {
data () {
return {
data: ''
}
}
}
</script>
I've looked all over the internet but nothing works on my side or I'm doing wrong :(
Thanks in advance
you can use like below:
Parent
<template>
<component #input-child="childData"></component>
</template>
<script>
import Component from "#/components/Component";
export default {
components: { Component },
data() {
return {
dataChild: ""
};
},
methods: {
childData(data) {
console.log(data);
// you can assign it to dataChild variable
}
}
};
</script>
Child
<template>
<input
type="text"
name="data"
v-model="data"
#input="$emit('input-child', data)"
class="form-control"
/>
</template>
<script>
export default {
data() {
return {
data: ""
};
}
};
</script>
The standard way to send data from child component to parent in vue is to emit that inside child and listen for event inside parent. Like this:
Child:
export default {
data: () => ({ dataChild: 'TEST' }),
methods: {
send () {
this.$emit('data', this.dataChild)
}
},
mounted () { this.send() }
}
Parent:
<div>
<child #data="get"></child>
</div>
export default {
data: () => ({ data: '' }),
methods: {
get(value) {
this.data = value
}
}
}

How do I trigger an AJAX request when props is changed?

I have a this App component
<template>
<div id="app">
<Component1 #addItem="addItem" />
<Component2 :items="items" />
</div>
</template>
<script>
import Component1 from './components/Component1'
import Component2 from './components/Component2'
export default {
name: 'app',
components: { Component1, Component2 },
data: function () {
return {
items: [],
}
},
methods: function () {
addItem(item) {
items.push(item)
},
},
}
</script>
This is my Component2 component:
<template>
<div>
{{ ajax_data }}
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Component2',
props: ['items'],
data: function () {
return {
ajax_data: null
}
},
mounted () {
this.callAJAX()
},
methods: {
callAJAX() {
axios
.get('/api/get-some-data', {
params: {
items: items
}
})
.then((response) => {
this.ajax_data = response.data
})
},
},
}
</script>
I want to trigger the AJAX everytime I add an item. The problem with my code is since Component2 is already mounted and when an item is added the AJAX is not running. So then I added this hook:
updated () {
this.callAJAX()
},
The problem with this is its running an infinite loop.
Is there a proper way to do this?
You can simply detect if value change with a watcher
https://v2.vuejs.org/v2/guide/computed.html#Watchers
https://v2.vuejs.org/v2/api/#watch
in your case, you may set the deep property to true...

Can’t select options from options list

I have a dropdown list called login. The list is shown when I load the page, but I can’t select an option from the list. Why is that?
I have searched the internet but didn’t find a solution.
This is the code from the component:
<template>
<div>
<label for="login" class="control-label">Logins anlegen für</label>
<select2 class="select2_tag form-control" name="login"
multiple="multiple" :options="login">
</select2>
</div>
</template>
<script>
import JQuery from 'jquery'
let $ = JQuery
import Select2 from '#/components/Select2.vue'
export default {
name: 'Login',
data: function () {
return {
login: [],
loginUebertrag: ''
}
},
components: {
Select2
},
methods: {
lade_login: function () {
let vm = this;
$.getJSON("/api/get_login.php", function (result) {
vm.login = result;
console.log("zeile 41: ", vm.login);
});
},
},
mounted()
{
this.lade_login();
}
}
</script>
And this is the code from the imported component (called select2):
<template>
<select class="form-control" >
<slot></slot>
</select>
</template>
<script>
import JQuery from 'jquery'
let $ = JQuery
export default {
name: 'select2',
props: ['options', 'value'],
mounted: function () {
var vm = this
$(this.$el)
// init select2
.select2({
data: this.options,
tags:true
})
//.val(this.value)
//.trigger('change')
// emit event on change.
.on('change', function () {
vm.$emit('input', this.value)
});
console.log( $(this.$el))
},
watch: {
value: function (value) {
// update value
//console.log(value)
$(this.$el)
.val(value)
.trigger('change')
},
options: function (options) {
// update options
$(this.$el).empty().select2({data: options,tags: true})
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
}
</script>
Any help is appreciated!

Make Chartkick wait for data to populate from Firebase before rendering chart

I'm using chartkick in my Vue project. Right now, the data is loading from Firebase after the chart has rendered, so the chart is blank. When I change the code in my editor, the chart renders as expected, since it's already been retrieved from Firebase. Is there a way to make chartkick wait for the data to load before trying to render the chart? Thanks!
Line-Chart Component:
<template>
<div v-if="loaded">
<line-chart :data="chartData"></line-chart>
</div>
</template>
<script>
export default {
name: 'VueChartKick',
props: ['avgStats'],
data () {
return {
loaded: false,
chartData: this.avgStats
}
},
mounted () {
this.loaded = true
}
}
</script>
Parent:
<template>
...
<stats-chart v-if="avgStatsLoaded" v-bind:avgStats="avgStats" class="stat-chart"></stats-chart>
<div v-if="!avgStatsLoaded">Loading...</div>
...
</template>
<script>
import StatsChart from './StatsChart'
export default {
name: 'BBall',
props: ['stats'],
components: {
statsChart: StatsChart
},
data () {
return {
avgStatsLoaded: false,
avgStats: []
}
},
computed: {
sortedStats: function () {
return this.stats.slice().sort((a, b) => new Date(b.date) - new Date(a.date))
}
},
methods: {
getAvgStats: function () {
this.avgStats = this.stats.map(stat => [stat.date, stat.of10])
this.avgStatsLoaded = true
}
},
mounted () {
this.getAvgStats()
}
}
modify your code of StatsChart component:
you may use props directly
<template>
<div v-if="loaded">
<line-chart :data="avgStats"></line-chart>
</div>
</template>
export default {
name: 'VueChartKick',
props: ['avgStats'],
data () {
return {
loaded: false,
}
},
mounted () {
this.loaded = true
}
}