How can I call apollo client conditionally in my vue template script? - javascript

I pass a query to apollo client in my script tag, in my template file but I don't want to do it every time. Rather, I'd like to pass a boolean in a prop and then run the query (or not) based on the boolean.
<template>
...
</template>
<script>
import {
MY_QUERY
} from 'util/queries';
props: {
productId: {
type: String,
default: '',
},
suppressGraphQlQuery: {
type: boolean,
default: false,
}
},
data() {
return {
relatedProducts: [],
loading: 0,
preloading: true,
};
},
apollo: {
relatedProducts: {
query: MY_QUERY,
variables() {
return {
id: this.productId,
};
},
},
},
</script>
I want to be able to utilize suppressGraphQlQuery prop not to call the apollo client, but not sure how to do it. Is it possible to not to run the query when my prop === true?
Thank you in advance.

You can skip a query like this:
export default {
props: {
skipQuery: {
type: Boolean,
default: false,
},
},
apollo: {
relatedProducts: {
query: MY_QUERY,
variables() {
return {
id: this.productId,
};
},
skip() {
return this.skipQuery;
},
},
},
};

Related

Reactive queries Apollo graphql in Vue 3

Trying to make a reactive query as per https://v4.apollo.vuejs.org/guide-option/queries.html#reactive-query-definition, but I can't get them to work.
Error:
Uncaught (in promise) Error: Invalid AST Node: { query: { kind: "Document", definitions: [Array], loc: [Object] }, loadingKey: "loading" }.
Query inside export default (checked is a reactive boolean v-model'ed to a button defined in data()):
apollo: {
getTags: getTags,
getPhotos: {
query() {
if (this.checked)
return {
query: getPhotos,
loadingKey: "loading",
}
else {
return {
query: getPhotosByTag,
loadingKey: "loading",
}
}
},
update: (data) => data.getPhotos || data.getPhotos,
},
},
GQL getPhotosByTag:
const getPhotosByTag = gql`
query getPhotosByTag {
getPhotos: findTagByID(id: 326962542206255296) {
photos {
data {
name
description
_id
}
}
}
}
`
GQL getPhotos:
const getPhotos = gql`
query getPhotos {
getPhotos: getPhotos(_size: 50) {
data {
name
description
_id
}
}
}
`
If I take them out into separate queries and try to instead update use skip() via checked and !checked in the query definition, only the initial load delivers a query, if I click the button new query doesn't launch. Queries work by themselves fine.
apollo: {
getPhotos: {
query() {
return this.checked ? getPhotos : getPhotosByTag
},
loadingKey: "loading",
update: (data) => data.getPhotos || data.getPhotos,
},
},
Loading key has to be on the same level as query

Vue: props doesn't get assigned automatically; when assigned manually - Avoid mutating a prop directly - error

I have two vue components: GetAnimal.vue and DisplayAnimal.vue. GetAnimal.vue send a JSON with animal data to DisplayAnimal.vue using router push. DisplayAnimal.vue displays that data. It works like this: I go to /getanimal, click a button that triggers the getAnimal() function which leads me to /viewanimal (via a router push):
GetAnimal.vue:
<script>
import axios from 'axios';
export default {
data: function () {
return {
name: 'defaultAnimal',
defaultanimal: {
name: 'Cat',
furColor: 'red',
population: '10000',
isExtinct: false,
isDomesticated: true
},
animal: String
}
},
methods: {
getAnimal: function () {
console.log("this.defaultanimal: " +
JSON.stringify(this.defaultanimal));
this.$router.push({
name: "viewanimal",
params: {
animal: this.defaultanimal
}
});
},
...
DisplayAnimal.vue:
<template>
<div>
<h1>Displaying animal:</h1>
<p>Animal name: {{animal.name}}}</p>
<p>Fur color: {{animal.furColor}}</p>
<p>Population: {{animal.population}}</p>
<p>Is extinct: {{animal.isExtinct}}</p>
<p>Is domesticated: {{animal.isDomesticated}}</p>
</div>
</template>
<script>
import axios from "axios";
export default {
props: {
animal: {
name: {
type: String
},
furColor: {
type: String
},
population: String,
isExtinct: String,
isDomesticated: String
}
},
name: "DisplayAnimal",
methods: {
},
created() {
console.log("animal param: " +
JSON.stringify(this.$route.params.animal));
this.animal = this.$route.params.animal;
}
};
</script>
The animal gets displayed just fine:
However I get the warning in console:
The this.animal = this.$route.params.animal; line that assigns the props explicitly is likely the cause of the warning.
However if I remove that line the animal doesn't get displayed at all:
I have this
router.js:
{
path: "/viewanimal",
name: "viewanimal",
component: () => import('./views/DisplayAnimal.vue'),
props: {animal: true}
},
{
path: "/getanimal",
name: "getanimal",
component: () => import('./views/GetAnimal.vue')
}
I thought setting props: {animal: true} would make sure it's autoassigned, but it doesn't seem to be the case. How should I fix it?
Well updating prop directly is an antipattern
It also doesnt make sense to have animal prop in DisplayAnimal component when you know it is not part of parent component which passes data to it. animal should be inside data so you can update in created callback.
Example
data() {
return {
loading: true, // perhaps you'd like to show loader before data gets fetched
animal: {
id: -1,
name: '',
furColor: '',
population: 0,
isExtinct: false,
isDomesticated: false
}
}
},
created() {
this.animal = this.$route.params.animal;
this.loading = false;
}

How use a mutation function in a action function in Vuex?

I have this Vuex:
export default new Vuex.Store({
state: {
userInfo: {
nit_ID: { ID: '', Desc: '' },
userName: { ID: '', Desc: '' },
typeDocument: { ID: '', Desc: '' },
document: '',
},
globalPublicKey: 'ASDFGHJKL1234567890',
},
mutations: {
updateUserInfo(state, payload) {
state.userInfo = payload;
},
},
getters: {
userInfo: (state) => { return state.userInfo; },
},
actions: {
validateUserSession(context) {
var valido = false;
try {
let storageInfo = JSON.parse(
sjcl.decrypt(context.state.globalPublicKey, localStorage.userInfo)
);
if (localStorage.userToken === storageInfo.token) {
context.mutations.updateUserInfo(storageInfo);
valido = true;
}
} catch (e) {
console.error(e);
}
return valido;
},
},
})
But the problem is that I can't access to the mutation updateUserInfo(), I know that is easy to solved, only do the updateUserInfo process in my action, but the question is How can I use a mutation into a action?
In VueJS you can call a mutation from an action by calling context.commit, like this:
context.commit('mutationName', params)
params can be omitted if not parameters are passed to the mutation.
More on this here: vuex.vuejs.org/guide/actions.html
Actually you call a mutation from anywhere with a commit - but it's advised to use actions (so dispatch an action) that in turn commits the data (actually mutates the state).

vue how set default props for nested object

my props is like this
house = {
kitchen:{
sink: ''
}
}
I tried something like this, didnt work.
props: {
house: {
type: Object,
default: () => {
kitchen : {
sink: ''
}
}
}
},
How to set default props for such object?
From the docs:
Object or array defaults must be returned from a factory function
So the problem is that you are not returning the default object.So you can either do:
props: {
house: {
type: Object,
default: () => ({ // <= note the parenthesis
kitchen : {
sink: ''
}
}) // <= here also
}
},
Or
props: {
house: {
type: Object,
default: () => {
return {
kitchen : { // <= note the return
sink: ''
}
}
}
}
},
The following solution should work :
props: {
house: {
type: Object,
default: () => ({
kitchen: {
sink:''
}
})
},
}
check this codesandbox
if the above solution doesn't work, you could use a normalized computed property :
props: {
house: { type: Object }
},
computed: {
normalizedHouse() {
return {
kitchen:{
sink: ''
}
}
}
}

How can I re-initialize (only) partial of data values in vue?

I know that we can re-initialize the data like this:
function initialData() {
return {
is_active: true,
is_collapsed: true,
resetable_data: 'value',
resetable_stat: 4
}
}
export default {
...
data() {
return {
initialData()
}
},
...
But I am wondering how we can re-initialize only a portion of the data. I mean something like:
function initialData() {
return {
resetable_data: 'value',
resetable_stat: 4
}
}
export default {
...
data() {
return {
is_active: true,
is_collapsed: true,
initialData()
}
},
...
Is there a way to do this?
Try Object.assign():
function initialData() {
return {
resetable_data: 'value',
resetable_stat: 4
}
}
export default {
...
data() {
return Object.assign(
{
is_active: true,
is_collapsed: true,
},
initialData()
);
},
...
Object.assign(target, ...sources) copies the properties of the ...sources (in this case, the object returned by initialData()) into the target (in this case the object with is_active and is_collapsed), returning the target object.

Categories

Resources