apollo vue query variable not recognizing data from page variable - vue.js

I have the following apollo query setup. I want to pass the username dynamically but this.username is not recognized.
My code:
export default {
data () {
return {
username: ''
};
},
beforeCreate () {
this.$Auth
.currentAuthenticatedUser()
.then((userProfile) => {
this.username = userProfile.username;
})
.catch(() => this.$router.push({ name: 'auth' }));
},
apollo: {
services: {
query: gql(servicesByUser),
variables: {
username: this.username
},
update: (data) => {
console.log('apollo:services', data);
return data.servicesByUser.items;
},
},
},
};
The below-hardcoded setup works:
variables: {
username: "user-a"
},
This setup does not work:
variables: {
username: this.username
},
Error:
TypeError: Cannot read property 'username' of undefined
at Module../node_modules/babel-loader/lib/index.js?!./node_modules/#quasar/app/lib/webpack/loader.auto-import.js?
I have spent a few hours on it, still not able to figure the issue! Am I missing anything? Any help is much appreciated!

variables should be a function in order for this to be defined, as shown in the docs:
apollo: {
services: {
...
variables () {
return {
username: this.username,
}
},
},
},

Related

Store user in vuex after login

I am trying to create login page. SO for this, I am making a call. After I get the response, I am storing cookie and with the cookie I am getting the user info. What I am trying to do is store this user info in Vuex store. Here is whole of my logic for this:
export default {
name: 'Login',
mounted() {
EventBus.$on(GENERAL_APP_CONSTANTS.Events.CheckAuthentication, () => {
this.authenticated = authHelper.validAuthentication();
if (this.authenticated) {
this.email = this.password = "";
this.authenticationFailed = false;
}
});
EventBus.$on(GENERAL_APP_CONSTANTS.Events.LoginFailed, () => {
this.authenticationFailed = true
});
},
data () {
return {
authenticated: false,
authenticationFailed: false,
email: '',
password: '',
rememberMe: false,
cookieName: "_token",
cookie: "",
cookieValue: "",
}
},
validations: {
email: {
required,
email,
},
password: {
required,
minLength: minLength(0)
},
},
methods: {
signIn: function () {
authHelper.signIn(this.email, this.password, () => {
this.$router.push({name: 'home'});
});
this.cookie = cookieHelper.getCookie(this.cookieName);
this.cookieValue = cookieHelper.getCookieValue(this.cookie);
this.storeUser();
},
storeUser: function () {
apiHelper.getRequest(
`/users/${cookieHelper.parseJwt(this.cookie).user_id}`,
(response) => {
this.$store.dispatch('storeUser', {
user: response.data,
})
}
)
},
}
}
So, as you see below, my user in Vuex store is still empty:
my mutation is:
export const STORE_USER = (state, {user}) => {
state.user = user;
}
my action is:
export const storeUser = ({commit}, {user}) => {
commit('STORE_USER', {user});
}
Could you have a look and let me know, where do you think I am making something wrong.

Vue.js Cannot read properties of undefined (reading 'router') error

I'm new to Vue.js and I have created one simple form for the user and storing data using API.
On submit I'm calling this function:
setup(props, { emit }) {
const blankData = {
customer: '',
template: '',
rate: '',
property_from: '',
property_to: '',
move_date: '',
num_days: '',
token: '',
details: '',
customer_options: [],
template_options: [],
rate_options: [],
property_from_options: [],
property_to_options: [],
}
const userData = ref(JSON.parse(JSON.stringify(blankData)))
const resetuserData = () => {
userData.value = JSON.parse(JSON.stringify(blankData))
}
const toast = useToast()
const onSubmit = () => {
store.dispatch('app-user/addUser', userData.value)
.then(
response => {
if (response.status === 1) {
this.$router.push({ name: 'edit-user', params: { id: 10 } })
}
toast({
component: ToastificationContent,
props: {
title: response.message,
icon: response.toastIcon,
variant: response.toastVariant,
},
})
},
error => {
console.log(error)
},
)
}
const {
refFormObserver,
getValidationState,
resetForm,
} = formValidation(resetuserData)
return {
userData,
onSubmit,
refFormObserver,
getValidationState,
resetForm,
}
},
And trying to redirect the user to the edit page after user creation but I'm getting this error and not redirecting:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'router')
I have tried with this stackoverflow answer but getting same error:
const onSubmit = () => {
const self = this
store.dispatch('app-user/addUser', userData.value)
.then(
response => {
if (response.status === 1) {
self.$router.push({ name: 'edit-user', params: { id: 10 } })
}
},
error => {
console.log(error)
},
)
}
Any idea what I'm doing wrong in my code?
You're using Vue 3 and a setup function; there is no this in a setup function.
See Accessing the Router and current Route inside setup.
Untested, but probably something like this will work:
setup() {
const router = useRouter()
const onSubmit = () => {
// ... code omitted ...
router.push({ name: 'edit-user', params: { id: 10 } })
}
return {
onSetup,
// other stuff...
}
}
I think this might be help
router with composition api
https://next.router.vuejs.org/guide/advanced/composition-api.html

Nuxt asyncData result is undefined if using global mixin head() method

I'm would like to get titles for my pages dynamically in Nuxt.js in one place.
For that I've created a plugin, which creates global mixin which requests title from server for every page. I'm using asyncData for that and put the response into storage, because SSR is important here.
To show the title on the page I'm using Nuxt head() method and store getter, but it always returns undefined.
If I place this getter on every page it works well, but I would like to define it only once in the plugin.
Is that a Nuxt bug or I'm doing something wrong?
Here's the plugin I wrote:
import Vue from 'vue'
import { mapGetters } from "vuex";
Vue.mixin({
async asyncData({ context, route, store, error }) {
const meta = await store.dispatch('pageMeta/setMetaFromServer', { path: route.path })
return {
pageMetaTitle: meta
}
},
...mapGetters('pageMeta', ['getTitle']),
head() {
return {
title: this.getTitle, // undefined
// title: this.pageMetaTitle - still undefined
};
},
})
I would like to set title in plugin correctly, now it's undefined
Update:
Kinda solved it by using getter and head() in global layout:
computed: {
...mapGetters('pageMeta', ['getTitle']),
}
head() {
return {
title: this.getTitle,
};
},
But still is there an option to use it only in the plugin?
Update 2
Here's the code of setMetaFromServer action
import SeoPagesConnector from '../../connectors/seoPages/v1/seoPagesConnector';
const routesMeta = [
{
path: '/private/kredity',
dynamic: true,
data: {
title: 'TEST 1',
}
},
{
path: '/private/kreditnye-karty',
dynamic: false,
data: {
title: 'TEST'
}
}
];
const initialState = () => ({
title: 'Юником 24',
description: '',
h1: '',
h2: '',
h3: '',
h4: '',
h5: '',
h6: '',
content: '',
meta_robots_content: '',
og_description: '',
og_image: '',
og_title: '',
url: '',
url_canonical: '',
});
export default {
state: initialState,
namespaced: true,
getters: {
getTitle: state => state.title,
getDescription: state => state.description,
getH1: state => state.h1,
},
mutations: {
SET_META_FIELDS(state, { data }) {
if (data) {
Object.entries(data).forEach(([key, value]) => {
state[key] = value;
})
}
},
},
actions: {
async setMetaFromServer(info, { path }) {
const routeMeta = routesMeta.find(route => route.path === path);
let dynamicMeta;
if (routeMeta) {
if (!routeMeta.dynamic) {
info.commit('SET_META_FIELDS', routeMeta);
} else {
try {
dynamicMeta = await new SeoPagesConnector(this.$axios).getSeoPage({ path })
info.commit('SET_META_FIELDS', dynamicMeta);
return dynamicMeta && dynamicMeta.data;
} catch (e) {
info.commit('SET_META_FIELDS', routeMeta);
return routeMeta && routeMeta.data;
}
}
} else {
info.commit('SET_META_FIELDS', { data: initialState() });
return { data: initialState() };
}
return false;
},
}
}

returning article by id -- vue router, vuex

I am trying to return article ID and go the detail page for that id. I did something like below. But in the end it's not working... in the console there is an error popping up and pointing that:
api/v1/article[object%20Object]:1 Failed to load resource: the server
responded with a status of 404 (Not Found)
I need some help because I am a bit lost here... What I am missing here? what I do wrong?
Vuex
export const articles = {
state: {
article: {},
},
mutations: {
setArticle(state, article){
state.article = article;
},
},
getters: {
loadArticle(state){
return state.article;
},
},
actions: {
getArticle(id){
axios.get("api/v1/article" + id)
.then(response => {
this.commit('setArticles', response.data);
})
.catch(error => {
console.log(error);
})
},
}
}
Routes
{
path: "detail/:id",
name: "detail",
component: Vue.component("Detail", require("./pages/Detail.vue").default),
meta: {
requiresAuth: true
}
},
Article Component
export default {
components: {
maps,
},
data(){
return {
};
},
created(){
this.$store.dispatch( 'getArticle', {
id: this.$route.params.id
});
},
computed: {
article(){
return this.$store.getters.loadArticle;
}
}
}
Link to the article id
<router-link :to="{ name: 'detail', params: { id: item.id } }">詳細を見る</router-link>
Update
First parameter to store action is the store properties itself. This is the reason you get the store object. You need to receive id or any payload as second parameter.
actions: {
getArticle({ commit }, id){
axios.get("api/v1/article" + id)
.then(response => {
commit('setArticles', response.data);
})
.catch(error => {
console.log(error);
})
},
}
Here you see this
created(){
this.$store.dispatch( 'getArticle', {
id: this.$route.params.id
});
},
You are passing an object as parameter-
{
id: this.$route.params.id
}
You should be doing this instead -
created(){
this.$store.dispatch( 'getArticle', this.$route.params.id);
},

VueJs 2 computed value cant read data

I'm trying to make a component for a login view. My app is really simple right now as I'm trying to learn Vue/Vuex.
In the sign in component, I want to check if the email is valid, using a computed value.
var emailRE = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export default {
name: "SignIn",
data: () => {
return {
email: "",
password: ""
};
},
computed: {
isValidEmail: () => {
return emailRE.test(this.email);
}
},
methods: {
signIn() {
if (this.isValidEmail) {
this.$store.dispatch("signIn", {
email: this.email,
password: this.password
});
}
}
}
};
However, the isValidEmail function throws an error in the console:
Uncaught TypeError: Cannot read property 'email' of undefined
Why can't my computed value read the this.email?
PS: I had to use data as a function according to the guidelines.
From the comments:
Actually, VSCode won't complain as there is no syntax error in your
code but its a wrong usage of the arrow function. In fact Vuejs docs
warns us against using arrow functions in the vue components
properties vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks .
For more on arrow function and 'this' usage check this article.
medium.freecodecamp.org/… . Its a 5 minute read article very plainly
written with nice example.
This now works:
var emailRE = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export default {
name: "SignIn",
data () {
return {
email: "",
password: ""
};
},
computed: {
isValidEmail () {
return emailRE.test(this.email);
}
},
methods: {
signIn () {
if (this.isValidEmail) {
this.$store.dispatch("signIn", {
email: this.email,
password: this.password
});
}
}
}
};