Pass data from Vue Component to Vuex store - javascript

I have the following Laravel api route
Route::get('c/maintenances/{contractor_user_id}', 'Maintenance\Api\ApiContractorMaintenanceController#index');
The contractor_user_id is dynamic and got from the database. I want to use it to get the resource collection returned by that particular contractor using the Vuex store
async getContractorMaintenances ({ commit, contractor_user_id }) {
let response = await axios.get(`/api/c/maintenances/${contractor_user_id}`)
commit('PUSH_CONTRACTOR_MAINTENANCES', response.data.data)
}
but the contractor_user_id is returning undefined when I console.log it
async getContractorMaintenances ({ commit, contractor_user_id }) {
console.log(`${contractor_user_id}`);
}
I have passed the contractor_user_id as a prop in the vue component
<script>
import { mapGetters, mapActions } from 'vuex'
import axios from 'axios'
export default {
props: {
contractor_user_id: {
required: true,
type: String
}
},
computed: {
...mapGetters({
contractor_maintenances: 'maintenance/contractor_maintenances',
})
},
methods: {
...mapActions({
getContractorMaintenances: 'maintenance/getContractorMaintenances',
}),
},
mounted () {
this.getContractorMaintenances()
}
}
</script>
How do I get the contractor_user_id to be passed on and be defined in Vuex?

You need to pass that id in mounted cycle of vue which means your action should be like:
async getContractorMaintenances ({ commit }, contractor_user_id) {
//code
}
and in mount cycle it should be like
this.getContractorMaintenances(this.contractor_user_id);

Related

Nuxt is throwing the error 'unknown action type' when I try to dispatch action from vuex store

I want to fetch some data from a firebase backend using an action to store it in vuex state. Currently I'm just working with some dummy data. Reading the data from the store in my index.vue works but as soon as I'm trying to get the action in index.vue I get the error that it is an unknown action type.
store/artikels.js
export const state = () => ({
artikel: [
{
id: "1",
titel: "Hallo",
untertitel: "Servas"
},
{
id: "2",
titel: "Was",
untertitel: "Wos"
},
{
id: "3",
titel: "Geht",
untertitel: "Wüst"
}
]
})
export const actions = () => ({
fetchArtikel() {
console.log('fetch data from firebase')
}
})
export const getters = () => ({
artikel: (state) => {
return state.artikel
}
})
this is index.vue
<script>
import { mapActions } from 'vuex'
export default {
name: 'App',
computed: {
artikel() {
return this.$store.state.artikels.artikel
}
},
async created() {
await this.$store.dispatch('artikels/fetchArtikel')
}
</script>
I've already tried to put the store in store/index.js without the namespace and also tried to dispatch it via mapActions and async fetch:
import mapActions from 'vuex'
methods: {
...mapActions(['artikels/fetchArtikels'])
}
or:
async fetch({store}) {
await store.dispatch('artikels/fetchArtikels')
}
So far, no luck. Can someone help me out? Thanks in advance!
The problem is your store's actions and getters are functions, but they need to be objects:
// store/artikels.js
export const actions = () => ({/*...*/}) // ❌ function
export const getters = () => ({/*...*/}) // ❌ function
export const actions = {/*...*/} // ✅ object
export const getters = {/*...*/} // ✅ object
demo

Vuex Mutation not updating the State

Working on a Vuejs application whereby I use Vuex for state management between the components.In Vuex store, I have an action that fetches some data from an API (which works fine) then populate it to the state (via a mutation). Next, I pass the updated state to the component using getters.
The problem is there is a problem populating data to the state from the action. In the DOM I have tried fetching via computed property or using the getter but get empty string
Vuex Store
const getDefaultState = () => {
return {
clientDeposit: ''
}
}
//state
const state = getDefaultState();
//getters
const getters = {
getDeposit: (state) => state.clientDeposit
}
//actions
const actions = {
fetchClients({ commit}) {
const clientId ="23"
axios.post('/api/motor/fetchClients', {
ClientId: clientId,
})
.then((response)=> {
//console.log(response); //returns data
const deposit = response.data;
commit('setIpfDeposit', deposit);
})
}
}
//mutations
const mutations = {
setIpfDeposit: (state, value) => (state.clientDeposit = value)
}
export default {
state,
getters,
actions,
mutations
}
Component
<template>
<div>
<button onclick="fetchClients()">Fetch Clients</button>
Deposit (Via computed property) : {{ fetchDeposit }}
Deposit (from getter) : {{ getDeposit }}
</div>
</template>
<script>
import { mapGetters , mapActions } from "vuex";
import axios from "axios";
export default {
name: "",
data() {
return {
}
},
computed: {
...mapGetters([
"getDeposit"
]),
fetchDeposit(){
return this.getDeposit
},
},
methods:{
...mapActions([
"fetchClients"
])
}
};
</script>
<style scoped>
</style>
You need to fetch the data first.
Import mapActions from vuex
import {mapActions, mapGetters} from 'vuex';
Bring in the fetchClients method in your component's methods object
methods:{
... mapActions(['fetchClients']),
}
Then in your component's created life cycle method call the fetchClients method
created(){
this.fetchClients();
}

Pass Laravel data to Vue component using vue router

I have a laravel collection that should pass json data to a vue component
$problems = $maintenance->getMaintenanceTypes();
return new MaintenanceTypesCollection($problems);
I'm then creating a radio button using that json collection
<div v-for="m_type in maintenance_types" :key="m_type.id">
<input type="radio" v-model="form.m_type" :value="m_type.id" :id="m_type.id">
<label :for="m_type.id">{{ m_type.problem }}</label>
</div>
and the data is being passed well when I'm using Laravel web routing but when I switch to Vue router the data is not being passed at all.
For reference here is my routes/api.php
Route::get('/maintenance/types', 'Maintenance\MaintenanceTypesController#index');
Here is my Vuex store
import axios from 'axios'
import { data } from 'jquery'
export default {
namespaced: true,
state:{
maintenance_types: []
},
getters:{
maintenance_types (state) {
return state.maintenance_types
}
},
mutations:{
PUSH_M_TYPE (state, data) {
state.maintenance_types.push(...data)
}
},
actions:{
async getMaintenanceTypes ({ commit }) {
let response = await axios.get('/maintenance/types')
commit('PUSH_M_TYPE', response.data.data)
}
}
}
And here is my Vue component script logic
import { mapGetters, mapActions } from 'vuex'
import axios from 'axios'
export default {
data () {
return {
form: {
description: '',
m_type: ''
}
}
},
computed: {
...mapGetters({
maintenance_types: 'maintenance/maintenance_types'
})
},
methods: {
...mapActions({
getMaintenanceTypes: 'maintenance/getMaintenanceTypes'
}),
async submit () {
await axios.post('/api/maintenance/store', this.form)
}
},
mounted () {
this.getMaintenanceTypes()
}
}
When I'm using this Vue routing it is not working
import AppMaintenanceForm from './components/maintenance/AppMaintenanceForm.vue'
export const routes = [
{
path: '/maintenance/form',
component: AppMaintenanceForm,
name: 'MaintenanceForm'
},
]
but when I switch to Laravel's routes/web.php it is working. What could be the problem? Thanks.

How to map state back to component in Vue.js AWS Amplify auth page

I am building an authentication page with Vue.js, Vuex, and AWS Amplify.
This auth page is based off Erik Hanchett's AWS Auth Example (https://github.com/ErikCH/Aws-auth-example/blob/master/src/components/HelloWorld.vue). Erik's original demo utilized Vuex for state management, but for the sake of simplicity only employs the state handler in the store.js file.
I am attempting to reconfigure this demo so that the various methods and hooks in HelloWorld.vue are set up to also dispatch actions and commit mutations.
So far, I have been successful in setting up the findUser() method in HelloWorld.vue to dispatch actions, pass user and signedIn as payloads to their respective action handlers, and then commit mutations.
However, my issue now pertains to the computed property in the HelloWorld component.
Erik's original demo returns the state directly to the component using return this.$store.state.signedIn as seen in the computed property. Based on my experience with Vuex in other projects, I would normally use a mapState helper to map directly to the state.
Is it correct in this project to use this.$store.state.signedIn to return the state? Or should I use mapState? If so, how can I reconfigure this computed property in order to employ mapState to map directly to signedIn?
My code is below:
HelloWorld.vue
<template>
<div class="hello">
<div v-if="!signedIn">
<amplify-authenticator></amplify-authenticator>
</div>
<div v-if="signedIn">
<Home></Home>
</div>
</div>
</template>
<script>
import { Auth } from 'aws-amplify'
import { AmplifyEventBus } from 'aws-amplify-vue';
import { mapState } from 'vuex'
import Home from '../components/Home.vue'
export default {
name: 'HelloWorld',
components: {
Home
},
data() {
return {
login: '',
password: ''
}
},
props: {
msg: String,
},
created(){
this.findUser();
AmplifyEventBus.$on('authState', info => {
if(info === "signedIn") {
this.findUser();
} else {
this.$store.state.signedIn = false;
this.$store.state.user = null;
}
});
},
computed: {
signedIn(){
return this.$store.state.signedIn;
}
},
methods: {
async findUser() {
try {
const user = await Auth.currentAuthenticatedUser();
let signedIn = true
this.$store.dispatch('setUser', user)
this.$store.dispatch('setSignedIn', signedIn)
}
catch(err) {
let signedIn = false
this.$store.dispatch('setSignedIn', signedIn)
}
}
}
}
</script>
Store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
user: null,
signedIn: false
},
mutations: {
setUser(state, user) {
state.user = user
},
setSignedIn(state, signedIn) {
state.signedIn = signedIn
}
},
actions: {
setUser: (context, user) => {
context.commit('setUser', user)
},
setSignedIn: (context, signedIn) => {
context.commit('setSignedIn', signedIn)
}
}
})
Home.vue
<template>
<div class="goodbye">
<h1>HOME</h1><br>
<amplify-sign-out></amplify-sign-out>
</div>
</template>
<script>
import { Auth } from 'aws-amplify'
export default {
name: 'Home',
data() {
return {
login: '',
password: ''
}
},
props: {
msg: String,
},
methods: {
signOut() {
Auth.signOut()
}
}
}
</script>
The mapState helper is just sugar syntax for not repeating multiple times the whole this.$store.state.foo piece of code.
You can certainly use mapState like this
import { mapState } from 'vuex'
computed: mapState([
// map this.signedIn to this.$store.state.signedIn
'signedIn'
])
Or like this if you want to also use local properties besides the ones of mapState
import { mapState } from 'vuex'
computed:
localComputed () { /* ... */ },
...mapState([
// map this.signedIn to this.$store.state.signedIn
'signedIn'
])
Here are the docs for more information on this.

vuex and axios debugging

I'm going crazy, I have a working api that sends data, I connected it to a VueJS app and it was working fine. I'm trying to implement Vuex and I'm stuck. Here's my store.js file
import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios'
Vue.use(Vuex);
const state = {
message: "I am groot",
articles: []
}
const getters = {
getArticles: (state) => {
return state.articles;
}
}
const actions = {
getArticles: ({ commit }, data) => {
axios.get('/articles').then( (articles) => {
commit('GET_ARTICLES', articles);
console.log(articles); // Trying to debug
}, (err) => {
console.log(err);
})
}
}
const mutations = {
GET_ARTICLES: (state, {list}) => {
state.articles = list;
}
}
const store = new Vuex.Store({
state,
getters,
mutations,
actions,
mutations
});
console.log(store.state.articles); // this lines works but data is empty
export default store
The console.log within axios call doesn't run and store.state.articles is empty. I must be missing something. I'm just trying to console the articles data on page load...
Please help, I'm near insanity :)
Component :
<template>
<div class="container">
<h1>Test component yo !</h1>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
name: 'Test',
computed: {
message() {
return this.$store.state.message
}
},
mounted: () => {
this.$store.dispatch('getArticles')
}
}
</script>
App.js :
import Vue from 'vue';
import ArticlesViewer from './articles_viewer.vue';
import UserArticles from './user_articles.vue';
import App from './app.vue'
import store from './store'
new Vue({
el: '#app-container',
store,
render: h => h(App)
})
You define the mounted lifecycle hook of your component using an arrow function.
As per the documentation:
Don’t use arrow functions on an instance property or callback (e.g. vm.$watch('a', newVal => this.myMethod())). As arrow functions are bound to the parent context, this will not be the Vue instance as you’d expect and this.myMethod will be undefined.
You should define it like so:
mounted: function () {
this.$store.dispatch('getArticles');
}
Or, use the ECMAScript 5 shorthand:
mounted() {
this.$store.dispatch('getArticles');
}
Now, your dispatch method will be called correctly, populating your articles array.

Categories

Resources