Call a method of another component - vuejs2

How to call a method of another component ?
Like I have a component named Modal.vue . I have a method like below
<script>
export default {
name: 'modal'
methods: {
getUsers() {
//some code here
}
},
created: function () {
this.getUsers();
}
}
</script>
I would like to call that method in another component named Dashboard.vue.
<script>
export default {
name: 'dashboard'
methods: {
add_adddress () {
this.getUsers(); // I would like to access here like this
//some code here
}
},
}
</script>
I read this question, but how can I use $emit,$on,$broadcast in my current setup ?

In order to use emit one of the components need to call the other (parent and child). Then you emit from the child component to the parent component. For example if Dashboard component uses the Modal component you can emit from the Modal to the Dashboad.
If your components are separate from one another you can make use of Mixins. You can create a mixin UsersMixin.js like the following:
export default {
methods: {
getUsers: function () {
// Put your code here for a common method
}
}
}
Then import the mixin in both your components, and you will be able to use its methods:
Modal.vue
<script>
import UsersMixin from './UsersMixin';
export default {
name: 'modal'
mixins: [
UsersMixin
],
created: function () {
this.getUsers();
}
}
</script>
Dashboard.vue
<script>
import UsersMixin from './UsersMixin';
export default {
name: 'dashboard',
mixins: [
UsersMixin
],
methods: {
add_adddress () {
this.getUsers(); // I would like to access here like this
//some code here
}
},
}
</script>

Related

Is it possible to dynamically add chart type in the extends: property, based on props from parent component?

I have a vue chartjs component which imports the whole vue-chartjs library. My idea is, is it possible to somehow pass the type of the chart which I want and add it to the 'extends: VueCharts.charttype?.' In the example I provide it extends the VueCharts.Line, I need this property to be dynamically interpolated, passed from props. Is it possible this charttype to come from a parent props dynamically and how?
<script>
import { VueCharts } from "vue-chartjs";
export default {
extends: VueCharts.Line,
props: ["chartdata", "options"],
mounted() {
this.renderChart(this.chartdata, this.options);
}
}
</script>
<style scoped>
</style>
since extends the same as mixins, you need to pass a dynamic mixin, in order to do that you need two components, imagine we have component ChartWrapper :
<template>
<div>
<div>{{ chartType }}</div>
<chart :chart-data="datacollection"/>
</div>
</template>
<script>
import Chart from "./Chart";
import { VueCharts, mixins } from "vue-chartjs";
const { reactiveProp } = mixins;
export default {
name: "ChartWrapper",
components: {
Chart
},
props: {
chartType: {
type: String,
required: true
}
},
data() {
return {
datacollection: {
labels: [this.getRandomInt(), this.getRandomInt()],
datasets: [
{
label: "Data One",
backgroundColor: "#f87979",
data: [this.getRandomInt(), this.getRandomInt()]
},
{
label: "Data One",
backgroundColor: "#f87979",
data: [this.getRandomInt(), this.getRandomInt()]
}
]
}
};
},
methods: {
getRandomInt() {
return Math.floor(Math.random() * (50 - 5 + 1)) + 5;
}
},
created() {
if (this.chartType) {
Chart.mixins = [reactiveProp,VueCharts[this.chartType]];
}
}
};
</script>
this component takes chartType as a prop, and I import all charts as VueCharts in top of the script ==> 1
second component:
<script>
export default {
props: ["options"],
mounted() {
// this.chartData is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.chartData, this.options);
}
};
</script>
the second component just has options props, and renderChart function invoked.
==> 2
What is happening?
the ChartWrapper component receives the chart type by chartType prop, in the created hook, if chartType exist, assign the chart(resolved by VueCharts[this.chartType]) to Chart component as a mixin in addition to reactiveProp,
I also pass the chart data to Chart component.
in the end, call the ChartWrapper component:
<ChartWrapper chartType="Bar"/>
Live example on code sandbox: https://codesandbox.io/s/vue-template-w9r8k
You can also choose for the option to just extend the Line chart and update the config of the chart with the chart type you want and give it an update so it changes type.
<script>
import { Line, mixins } from 'vue-chartjs';
const { reactiveProp } = mixins;
export default {
extends: Line,
name: "LineChart",
mixins: [reactiveProp],
props: {
options: { type: Object },
chartType: { type: String }
},
mounted () {
this.renderChart(this.chartData, this.options);
},
watch: {
options: {
deep: true,
handler () {
this.$data._chart.options = this.options;
this.updateChart();
}
},
chartType (newVal) {
this.$data._chart.config.type = newVal;
this.updateChart()
}
},
methods: {
updateChart () {
this.$data._chart.update();
},
}
}
</script>

How to hook lifecycle events from root App component in Vue.js

The structure of the app:
src/
|-- App.vue
|-- components/
|-- MyComponent.vue
|-- OtherComponent.vue
If I do, in MyComponent.vue
// MyComponent.vue
export default {
name: 'MyComponent',
methods: {
mounted() {
alert('MyComponent mounted')
}
}
}
This works as expected — an alert box is triggered when the component is mounted.
However, if I do the exact same thing in App.vue:
// App.vue
import MyComponent from './components/MyComponent.vue'
import OtherComponent from './components/OtherComponent.vue'
export default {
name: 'app',
components: {
MyComponent,
OtherComponent
},
methods: {
mounted() {
alert('app mounted')
}
}
}
Then nothing happens. I've tried with created, mounted, I've also try to wrap the alert() call into this.$nextTick({ ... }) — no success.
My problem is: I want something to happen (in this example, alert('app mounted')) once the child components have been mounted, because this "thing" needs to have all components mounted before executing.
Is it possible to hook a lifecycle event (ideally, mounted) in the App component?
All lifecycle methods need not to be declared within methods.
Should be as below.
// App.vue
import MyComponent from './components/MyComponent.vue'
import OtherComponent from './components/OtherComponent.vue'
export default {
name: 'app',
components: {
MyComponent,
OtherComponent
},
mounted() {
alert('app mounted')
},
methods: {
}
}
For more details read here
mounted is life cycle method of vue component. don't put it in methods.
Change
// MyComponent.vue
export default {
name: 'MyComponent',
methods: {
mounted() {
alert('MyComponent mounted')
}
}
}
To
// MyComponent.vue
export default {
name: 'MyComponent',
methods: {
},
mounted() {
alert('MyComponent mounted')
}
}

Value from other Vue component

How can I get the value of an element in another Vue component and use it in another Component. For example I want to get the value of a textbox from a separate component and use it another.
By using event bus to communicate between any components,
Component A:
<script>
export default {
name: 'ComponentA',
methods: {
onTextAreaChange: function(event) {
this.$root.$emit('changed', event)
}
}
}
</script>
Component B:
<script>
export default {
name: 'App',
mounted() {
this.$root.$on('changed', (data) => {
//...console data here
})
}
}
</script>

Vue.js parent-child components , why my prop is not yet available in child component?

In a parent component Member.vue , I get the user and account data from Vuex store via getters
<script>
import { mapGetters } from 'vuex'
import Profile from '#/components/Member/Profile.vue'
export default {
name: 'member',
components: {
Profile
},
data () {
return {
}
},
computed: {
...mapGetters(['user', 'account'])
},
methods: {
},
created () {
console.log('MEMBER VUE CREATED user: ', this.user)
console.log('MEMBER VUE CREATED account: ', this.account)
}
}
</script>
In the child component profile , I get the user data from props, but it's undefined ...
<script>
export default {
name: 'profile',
props: ['user'],
computed: {
...
},
methods: {
...
},
created: function () {
console.log('user data from parent component:')
console.log('user: ', this.user)
}
}
</script>
I guess it's related to the Parent-Child lifecycle hooks... but I don't see actually how to solve it easily ... thanks for feedback
In your HTML you need to pass the property down to the children, in your case it would be something like:
<profile :user="user" ...></profile>

Write a Global Methods to check authentication in NuxtJS

I have difficulty to Write a Global Methods to check authentication in NuxtJS. The methods which I can write v-if in components to display if it return True.
I put this code in layout/default.vue but it doesn't works.
/layout/defaut.vue
<script>
import '~/assets/icons'
export default {
head () {
return !this.mobileLayout ? {} : {
bodyAttrs: {
class: 'mobile'
}
}
},
created () {
this.LoggedIn()
},
methods: {
LoggedIn: function () {
return this.$store.state.authUser
}
}
}
</script>
Components:
<template>
<div v-if="LoggedIn">Authenticated</div >
</template>
Error:
Property or method "LoggedIn" is not defined on the instance but referenced during render
Hope you guy help me!
Since authUser is a state property in vuex, not a method. LoggedIn in your component is simply returning a value from the state and does not need to be a method.
You should use a computed instead of a method. You also do not need to call LoggedIn from the created method, once it is a computed, it will be calculated automatically.
<script>
import '~/assets/icons'
export default {
head () {
return !this.mobileLayout ? {} : {
bodyAttrs: {
class: 'mobile'
}
}
},
computed: {
LoggedIn: function () {
return this.$store.state.authUser
}
}
}
</script>
Or even better, use mapState from vuex which is documented here https://vuex.vuejs.org/en/state.html
<script>
import Vuex from 'vuex'
import '~/assets/icons'
export default {
head () {
return !this.mobileLayout ? {} : {
bodyAttrs: {
class: 'mobile'
}
}
},
computed: {
...mapState({
LoggedIn: 'authUser'
})
}
}
</script>
Your template does not need to be changed.