Is there a thing in Vuex that work the same as mapDispatchToProps in Redux? - vue.js

I was trying to do things like this.updateData() instead of this.$store.dispatch() in a child component, where the updateData is a function inherits from its parent component. Anyone have any idea how to achieve that?

So to update data of parent comp. from child component in Vue we can utilize event bus:
Parent:
<template>
Hi Blake...
<child-component #trigger="updateData()"></child-component>
</template>
<script>
export default {
mounted() {},
methods: {
updateData: function() {
// this will be triggered from child
}
}
}
</script>
Child ( child-component ):
<template>
<button #click="$emit('trigger')">Trigger Parent Function</button>
</template>
<script>
export default {
mounted() {}
}
</script>
Now this only triggers parent function but you can also send data with event that will be received by parent. This is just Vue without Vuex. If I'm wrong and you're not looking for this maybe you want to use Vuex mapActions which can be used to import all Vuex actions you need in your component and use them as this.vuexAction instead of this.$store.dispatch('vuexAction').
I hope I helped. Good luck.

Related

How to call methods from the parent component in child in vuejs

I have a click event and with this click event I want to call function/methods which is in parent component. So the click event in my child component:
<button #click.native="addNew" />
Here is my method:
methods: {
addNew() {
this.$parent.addNew();
},
},
Ad I want to call this function in my parent component:
addNew() {
this.$emit('open');
},
But I a getting an error like: this.$parent.addNew is not a function. How can I fix it?
Based on $emit event in Vue.js: https://vuejs.org/guide/components/events.html
When you emit an event like this: $emit('someEvent'), the parent someEvent function will fire (and also you can pass some parameters).
So you must listen to the 'someEvent' function in parent.
EDIT: this link would be a good example: https://learnvue.co/tutorials/vue-emit-guide
Here is a basic example working with events
Child.vue
<template>
<button #click="$emit('childClick')">click me</button>
</template>
Parent.vue
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
function onChildClick(){
console.log("child has clicked")
}
</script>
<template>
<Child #childClick="onChildClick"></Child>
</template>

Calling function inside child component without an event?

Currently trying to use a method belonging to the parent
<p class="message-date text-center">
{{ $emit('format_date_day_month_year_time', message.date) }}
</p>
However I am getting the error.
Converting circular structure to JSON
--> starting at object with constructor 'Object'
How can I call a function inside a child component that does not rely on an event? I apologize for asking such a simple question but everything I was able to find on google is using $emit and using an event.
$emit was designed to only trigger an event on the current instance of vue. Therefore, it is not possible to receive data from another component this way.
For your case, I would suggest to use Mixins especially if you need to use certain functions among multiple vue components.
Alternately, let the child component call the the parent through $emit then receive the result from the parent through a prop.
Your code could be something as follows:
Child component
<template>
<p class="message-date text-center">
{{ date }}
</p>
</template>
<script>
export default {
name: 'Child',
props: {
date: String,
},
mounted() {
this.$emit("format-date", message.date);
},
}
</script>
Parent component
<template>
<Child :date="childDate" #format-date="formatChildDate" />
</template>
<script>
import Child from '#/components/Child';
export default {
components: {
Child,
},
data: () => ({
childDate: '',
}),
methods: {
formatChildDate(date) {
this.childDate = this.formatDateDayMonthYearTime(date)
},
formatDateDayMonthYearTime(date) {
//return the formatted date
},
},
}
</script>
with $emit you call a function where the Parent can listento.
where you are using it i would suggest a computed prop of the function.
But back to your Question here is a example of emiting and listen.
//Parent
<template>
<MyComponent #childFunction="doSomethingInParent($event)"/>
</template>
//Child
<template>
<button #click="emitStuff">
</template>
.....
methods:{
emitStuff(){
this.$emit(childFunction, somedata)
}
with the event you can give Data informations to a Parentcomponent.

Dynamically update props

As simplified below, my app has a template with a custom component.
The data is passed from Template A to custom component as props (":list")
Template A:
<template>
...
<custom-component
v-for="list in listGroup"
:key="list.id_list"
:list="list"
/>
</template>
<script>
export default {
data() {
return {
listGroup: []
};
},
components: {
'custom-component':require("...").default
}
</script>
The custom component
<template>
...
</template>
<script>
export default {
props:["list];
...
}
</script>
Problem to solve:
A new item is added to the list sent as props.
I need the list (:list="list") to be dynamically updated so that the props in the custom component automatically reflect that update.
Thanks.
There are two ways to achieve that one way is to use a state management library(Vuex is recommended) the other is to use events.
Here is an example of using events:
create a file event-bus.js with the following content
import Vue from "vue";
export const EventBus = new Vue();
then in your component where you want to update list use this EventBus.$emit('eventName', data);
remember to import event-bus file
the listen to the event in the other component
EventBus.$on('eventName', function (details) {
//update list here
});

How to update the value of child component's props from parent component?

From my parent component, I need to trigger a child component's portion of code containing a Firebase query. Note that in the child component, that code is triggered within the mounted() hook (but in order to execute it from the parent component, I suppose I will have to move that code to a method or something).
What is the recommended way to achieve such a thing?
Here's my parent component code - simplified for clarity:
<template>
<div>
<nav>
<v-btn #click="viewNextWeek"></v-btn>
</nav>
<project-row :mon="mon"></new-row-form>
</div>
</template>
<script>
import ProjectRow from './ProjectRow.vue';
import store from '../store';
import moment from 'moment';
export default {
name: 'home',
components: {
ProjectRow
},
data() {
return {
mon: moment().startOf('isoWeek')
}
},
methods: {
viewNextWeek: function() {
this.mon = moment().startOf('isoWeek').add(7, 'days');
}
}
}
</script>
Child component - simplified too:
<template>
<div>
<input v-model="monTime">
</div>
</template>
<script>
import { db } from '../firebase';
export default {
props: [
'mon'
],
mounted() {
var timesRef = db.collection('times');
var timesWeek = timesRef.where('date', '==', this.mon);
timesWeek.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.monTime = doc.data().time;
});
})
.catch(function(error) {
console.log('Error getting documents: ', error);
});
}
}
</script>
to achieve that you should use event bus communication between these two components. first, you should create a global event bus that can be a central event management and will give you the possibility to access any event from any component within your vuejs app. in your case here, you should emit an event from your parent component within viewNextWeek method and catch it within mounted in child component. so every time your mon value change within your parent component, will trigger an event to the child component to update mon within it.
for more detail for how to use global event bus, read this article global event bus article

Pass information from a child component to a parent component with Vue.js

Thanks for reading my question.
I have doubts about how to accomplish this in my Vue.js app.
Parent Component: App.vue
Child Components: Loading.vue, ProductsList.vue, NoProductList.vue
The App component is the container. When the page loads, the Loading component is displayed.
The Loading component then checks for products. If there are products the Loading component will return the products as an object.
If there aren't any products the Loading component will return null.
How do I tell the App component which component to use based on the Loading components return value? ie.. Load the ProductsList component if there are products and the NoProduct component when there aren't any products?.
What's the correct way to do notify the parent component about which component it should use in Vue?
Should I use $emit (pass data from child to parent), State Management https://v2.vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch or a Bus component?
Some code...
Loading.vue component (child):
export default {
name: 'loading',
data () {
return {
message: ''
}
},
mounted: function () {
this.loadingProcess();
},
methods: {
loadingProcess: function () {
//process
this.$emit('found-products', 'hola');
}
}
App.vue component (parent):
<template>
<div>
<div id="resultComponent" #found-products="checkProductsList">
<loading></loading>
...
</div>
</div>
</template>
Thanks in advance.
For parent-child interactions, the correct way is for the child to $emit and the parent to set props.
State management and buses are for more complex systems where data must be shared by not-closely-related components.