module getters not updating in vue component - laravel-5.3

I'an not using getters.js file seperately, instead getters are written in js->assets->store->modules->user.js file
This is my user.js
const state = {
count : '',
list:[]
};
const mutations = {
COUNT: (state, data) => {
state.count = data
},
LIST : (state, data) => {
state.list = data
}
};
const getters = {
userCount:(state) => state.list.length
};
const actions = {
getList: ({commit,state}) => {
axios.get('/api/user/list')
.then((response) => {
commit('LIST', response.data);
})
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
This is my user vue component-user.vue
<template>
<div class="col-lg-3 col-xs-6">
<div class="small-box bg-yellow">
<div class="inner">
<h3>{{ usercount }}</h3>
<p>User Registrations</p>
</div>
<div class="icon">
<i class="ion ion-person-add"></i>
</div>
View <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
</template>
<script>
export default{
computed: {
usercount() {
return this.$store.getters['user/userCount'];
}
},
mounted(){
this.$store.dispatch('user/getList');
}
}
</script>
In user.js,
alert(state.list.length)
gives the correct count in the alert box.
But in user.vue,
alert(this.$store.getters['user/userCount'])
gives 'undefined'

remove unnecessary : from this:
const getters = {
userCount (state) => state.list.length
};

In the Api controller, I'am using paginate() instead of get().vue dev tools helped me to find out this...
getList: ({commit,state}) => {
axios.get('/api/user/list')
.then((response) => {
commit('LIST', response.data);
})
}
changed response.data to response.data.data

Related

How to update the state in pinia with Vue 3

I'm trying to save the input values in the Pinia store, but the state is not updating. So I want onSubmit function to save the input values in a store.
My code :
Create.vue
<script setup>
import { reactive } from "vue";
import { useCounterStore } from '#/stores/counter';
const counter = useCounterStore();
const form = reactive({
first: "",
second: "",
email: ""
});
const onSubmit = (e) => {
e.preventDefault();
counter.$patch({ firstName: form.first.value });
counter.$patch({ secondName: form.second.value });
counter.$patch({ email: form.email.value });
}
</script>
<template>
<form #submit="onSubmit">
{{ counter.getFirst + 'MYFIRST' }} {{ counter.getSecond + 'MYSECOND' }} {{ counter.getEmail + 'MYEMAIL' }}
<div class="row mt-4">
<div class="col-6">
<label for="exampleFormControlInput1" class="form-label">First</label>
<input v-model="form.first" type="text" class="form-control" id="exampleFormControlInput1"
placeholder="First name">
</div> <div class="col-6">
<label for="exampleFormControlInput1" class="form-label">Second</label>
<input v-model="form.second" type="text" class="form-control" id="exampleFormControlInput1"
placeholder="Second name">
</div>
<div class="col-6 mt-2">
<label for="exampleFormControlInput1" class="form-label">Email</label>
<input v-model="form.email" type="email" class="form-control" id="exampleFormControlInput1"
placeholder="name#example.com">
</div>
<div class="col-12 mt-3">
<button #click="onSubmit" type="button" class="btn btn-dark push- right">Create</button>
<button type="button" class="btn btn-dark">All users</button>
</div>
</div>
</form>
</template>
Pinia store: counter.js
import { ref, computed, reactive } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0);
let firstName = ref('');
let secondName = ref('');
let email = ref('');
const getFirst = computed(() => firstName.value)
const getSecond = computed(() => secondName.value)
const getEmail = computed(() => email.value)
function increment() {
count.value++
}
return { count, getFirst, getSecond, getEmail, increment }
})
i am not sure how your store look like... but it should by something like:
`
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
}
})`
in your component, change the name of the store instance, lets say counterStore.
const counterStore = useCounterStore();
and now you can access the state by name:
counterStore.counter++
while this will work, it is not the best practice...
you should use actions to manipulate the state...
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
actions: {
increment() {
this.count++
},
},
})
and then you can call the action like a regular method:
counterStore.increment()
I think you're in the process of learning Vue, don't give up!
Give a feedback in comment and put your post on "solved" status if this help you.
The solution :
In store file :
import { defineStore } from 'pinia';
export const useAuthStore = defineStore('auth', {
state: () => ({
loginForm: {
firstName: '',
secondName: '',
email: ''
}
})
});
In Create.vue :
<script setup>
import { reactive } from "vue";
import { useAuthStore } from '#/stores/auth';
const authstore = useAuthStore();
const form = reactive({
first: "",
second: "",
email: ""
});
...
const onSubmit = (e) => {
e.preventDefault();
authStore.loginForm.firstName = form.first;
authStore.loginForm.secondName = form.second;
authStore.loginForm.email = form.email;
}
...
<script/>

How to use a method inside v-if

I'm trying to display countries from database which the continentId foreach country == logged user scope.
An user scope is between 1-5.
here is my vue template
<div class="container w-75" v-show="showGrid">
<div class="row" style="width:900px; height:900px; padding-left:200px">
<div class="col-md-4" v-for="country of countries" v-bind:key="country">
<div v-if="country.continentId==setup" class="card p-3" style="cursor:pointer">
<router-link :to="{ path: '/FetchData', query: { query: country.countryName}}">
<div class="d-flex flex-row mb-3">
<div class="d-flex flex-column ml-2"><span>{{country.countryId}}</span></div>
</div>
<h6 style="text-align:left">{{country.countryName}}</h6>
</router-link>
</div>
and those are my methods
export default {
methods: {
async getCountries() {
let country = this.$route.query.query
if (!country) {
await axios
.get("https://localhost:44391/api/Pho/GetCountries")
.then((res) => (this.countries = res.data))
} else {
await axios
.get(
"https://localhost:44391/api/Pho/GetCountries?country=" +
this.$route.query.query
)
.then((res) => (this.countries = res.data))
this.searchbar = false
}
},
async setup() {
let token = "??"
const scope = ref("")
const response = await fetch(
"https://localhost:44391/api/Auth/UserScope",
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
credentials: "include",
}
)
const content = response.json()
scope.value = `${content.scope}`
return {
scope,
}
},
},
async mounted() {
this.setup()
await this.getCountries()
},
}
the method setup return le scope of the logged user and the getCountries method returns the list of countries.
when i inspect i find that the scope is returned but the <div v-if="country.continentId==setup" class="card p-3" style="cursor:pointer"> condition does not work properly.
The setup() hook is not supposed to be under methods. It needs to be at the top level of the object:
export default {
methods: {
// setup() { /*...*/ } ❌
},
setup() { /*...*/ }, ✅
}
Also, don't make the setup() hook async unless you're intentionally making it an async component, which requires a <Suspense> as an ancestor. Instead, move the asynchronous code into its own function within:
export default {
setup() {
const scope = ref('')
const fetchUserScope = async () => {
const response = await fetch(/*...*/)
const content = await response.json()
scope.value = content.scope
}
fetchUserScope()
return { scope }
}
}
Also, you can't invoke the setup() hook from the template like that. You're really just trying to compare continentId to the scope value, so use scope directly:
<!-- <div v-if="country.continentId == setup"> --> ❌
<div v-if="country.continentId == scope"> ✅
You shouldn't try to invoke setup() from mounted() hook either. Vue controls the lifecycle hooks itself:
export default {
mounted() {
// this.setup() ❌
}
}

Uncaught Error: When called with an action of type "DELITEM", the slice reducer for key "addItem" returned undefined

Uncaught Error: When called with an action of type "DELITEM", the slice reducer for key "addItem" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.
What is this error when I open inspection. My problem is that Onclick is not working in my app.
Here is the code:
import React from 'react'
import { useSelector } from 'react-redux'
import { useDispatch } from 'react-redux'
import { delItem } from '../redux/actions/index'
import { NavLink } from 'react-router-dom'
const Cart = () => {
const state = useSelector((state)=> state.addItem)
const dispatch = useDispatch()
const handleClose = (item) => {
dispatch(delItem(item))
}
const cartItems = (cartItem) => {
return(
<div className="px-4 my-5 bg-light rounded-3" key={cartItem.id}>
<div className="container py-4">
<button onClick={()=>handleClose(cartItem)} type="button" className="btn-close float-end" aria-label="Close"></button>
<div className="row justify-content-center">
<div className="col-md-4">
<img src={cartItem.image} alt={cartItem.title} height="200px" width="180px" />
</div>
<div className="col-md-4">
<h3>{cartItem.title}</h3>
<p className="lead fw-bold">${cartItem.price}</p>
</div>
</div>
</div>
</div>
);
}
Action:
export const addItem = (product) => {
return {
type : "ADDITEM",
payload : product
}
}
export const delItem = (product) => {
return {
type : "DELITEM",
payload : product
}
}
Reducers:
const addItem = [];
const addItems = (state = addItem, action) => {
switch (action.type) {
case "ADDITEM": return [
...state,
action.payload
]
break;
case "DELITEM": return
return state = state.filter((x)=>{
return x.id !== action.payload.id
})
break;
default: return state;
break;
}
}
export default addItems;
case "DELITEM": return
return state = state.filter((x)=>{
return x.id !== action.payload.id
})
change above code to :
make it to "DELITEM": return [...state.filter((x)=>{
return x.id !== action.payload.id
})]

Need help in my VueJS + VueX + Firebase project

I am trying to show the current userName and title which was already created by signin and now stored in Firebase Cloud Firestore database.
But I don't know how to handle this, I can't find an error in the code by my self.
Here is the code:
<template>
<div id="dashboard">
<section>
<div class="col1">
<div class="profile">
<h5>{{ userProfile.name }}</h5>
<p>{{ userProfile.title }}</p>
<div class="create-post">
<p>create a post</p>
<form #submit.prevent>
<textarea v-model.trim="post.content"></textarea>
<button #click="createPost"
class="button">post</button>
</form>
</div>
</div>
</div>
<div class="col2">
<div>
<p class="no-results">There are currently no posts</p>
</div>
</div>
</section>
</div>
</template>
<script>
const fb = require('../firebaseConfig.js')
import { mapState } from 'vuex'
import firebase from 'firebase'
const db = firebase.firestore()
export default {
data() {
return {
post: {
content: ''
}
}
},
computed: {
...mapState(['userProfile'])
},
methods: {
createPost() {
fb.postsCollection.add({
createdOn: new Date(),
content: this.post.content,
userId: this.currentUser.uid,
userName: this.userProfile.name,
comments: 0,
likes: 0
}).then(ref => {
this.post.content = ''
}).catch(err => {
console.log(err)
})
}
}
}
</script>
Store.js
import Vue from 'vue'
import Vuex from 'vuex'
const fb = require('./firebaseConfig.js')
Vue.use(Vuex)
// handle page reload
fb.auth.onAuthStateChanged(user => {
if (user) {
store.commit('setCurrentUser', user)
store.dispatch('fetchUserProfile')
}
})
export const store = new Vuex.Store({
state: {
currentUser: null,
userProfile: {}
},
actions: {
clearData ({ commit }) {
commit('setCurrentUser', null)
commit('setUserProfile', {})
},
fetchUserProfile ({
commit,
state
}) {
fb.usersCollection.doc(state.currentUser.uid).get().then(res => {
commit('setUserProfile', state.res.data())
}).catch(err => {
console.log(err)
})
console.log(state)
}
},
mutations: {
setCurrentUser (state, val) {
state.currentUser = val
},
setUserProfile (state, val) {
state.userProfile = val
}
}
})
Error output:
userProfile output as Object:

Can't read property 'bind' of undefined

OS: Windows 10 Pro
apollo-client: 1.9.2
react-redux: 5.0.6
So, I'm attempting to read 'connect' a graphql resultset to redux but am receiving the above mentioned error message. My code is as follows:
import { connect } from 'react-redux';
class PhotoGrid extends React.Component {
render () {
const { data } = this.props;
const isNewPage = this.props.location.pathname.includes('new');
if (data.loading) {
return <p>Loading ...</p>;
}
if (data.error) {
return <p>{data.error.message}</p>;
}
return (
<div>
<div>Total record count: {data._allPostsesMeta.count}</div>
<div className="photo-grid">
{ data.allPostses.map( (post,i) => <Photo {...this.props} key={i} postIndexID={i} post={post} />) }
</div>
{isNewPage && (
<div>
<div onClick={() => this.previousPage()}>
Previous
</div>
<div onClick={() => this.nextPage()}>
Next
</div>
</div>
)}
</div>
);
}
};
const allPostsCommentsQuery = graphql(All_Posts_Comments_Query, {
options: ownProps => {
const page = parseInt(ownProps.match.params.page, 10);
const isNewPage = ownProps.location.pathname.includes('new');
const skip = isNewPage ? (page - 1) * parseInt(PRODUCTS_PER_PAGE) : 0;
const first = isNewPage ? parseInt(PRODUCTS_PER_PAGE) : parseInt(PRODUCTS_PER_PAGE);
const orderBy = isNewPage ? OrderBy : null;
fetchPolicy: 'network-only';
return {
variables: {
__offline__: true,
first,
skip,
orderBy,
},
}
},
});
export default connect(allPostsCommentsQuery)(PhotoGrid)
What am I overlooking here?

Resources