In Nuxt.js, I'm trying to do a query like this with the nuxt apollo-module based in vue-apollo
apollo: {
magazines: {
query: gql`query($id: String!) {
magazines( where: { url_contains:$id })
{
url
title
thumbnail
}
}`,
prefetch: ({ route }) => ({ id: route.params.id }),
variables() {
return {
id: this.$route.params.id
}
}
}
The query is sent, but the variable $id is sent unrendered (in the petition, I can see query($id: String!)—instead of query('my-page-route': String!)— and where: { url_contains:$id } as it is—instead of where: { url_contains:'my-page-route' }
The query is surprisingly valid, as it responds with all the items in the db —so it doesn't apply the where: { url_contains:$id }
I have tried with query($id: String) but that doesn't change anything. Any hints about what could be going wrong?
Thanks in advance!
Related
I'm using expressjs and apollo-server-express. I'm trying to set up a query in graphql to return a product from my database. The problem is that the results never show up in graphql, but when I console log resultsArr the results show up fine. Just to note the resultsArr is an array of objects.
Express:
const typeDefs = gql`
type Search {
brand: String
title: String
url: String
thumbnail: String
}
type Query {
results(query: String!): Search
}
`;
const resolvers = {
Query: {
results: (parent, args) => {
const queries = [
{
indexName: 'products',
query: args.query,
params: {
hitsPerPage: 1,
},
},
//
];
return AlgoliaClient.multipleQueries(queries).then(({ results }) => {
// Store Results
const resultsArr = [];
results.forEach((item) => {
resultsArr.push(item.hits[0]);
});
// console logging this shows the products
return resultsArr;
});
},
},
};
and my query the graphql playground is:
query Search {
results(query: "Test product") {
title
}
}
The problem is when I console log resultsArr the products show up no problem, however when it try it though the query I get:
{
"data": {
"results": {
"title": null
}
}
}
In my vue screen I'd like to use one apollo graphql I've defined for two properties. As far as I understand the name of the property must match a name of the attribute in the returned json structure.
I naivly tried to use the queries for two properties but it throws an error for the second one.
...
data() {
return {
userId: number,
user: null as User | null,
previousUserId: number,
previousUser: null as User | null
};
},
...
apollo {
user: {
query: READ_ONE_USER,
variables() {
return {
userId: this.userId
};
}
},
previousUser: {
query: READ_ONE_USER,
variables() {
return {
userId: this.previousUserId
};
},
export const READ_ONE_USER = gql(`
query user($userId: Int!) { user(userId: $userId)
{
id
firstName
lastName
email
}
}
`);
I expected no problems but I get "Missing previousUser attribute on result {user: ...}"
Daniel's solution didn't work out for me, I still got the same error message.
But there's another way to do it, you can provide an update function to tell apollo how to extract the result out of the data read from the server:
apollo {
user: {
query: READ_ONE_USER,
variables() {
return {
userId: this.userId
};
}
},
previousUser: {
query: READ_ONE_USER,
variables() {
return {
userId: this.previousUserId
};
},
update(data) {
return data.user;
}
}
This is documented at https://github.com/vuejs/vue-apollo/blob/v4/packages/docs/src/api/smart-query.md#options
As shown in the docs, you can manually add smart queries inside the created hook:
created () {
this.$apollo.addSmartQuery('user', {
query: READ_ONE_USER,
variables() {
return {
userId: this.userId
};
},
})
this.$apollo.addSmartQuery('previousUser', {
query: READ_ONE_USER,
variables() {
return {
userId: this.previousUserId
};
},
})
}
I would like to create a checkout object via the GraphQL API provided by the Saleor eCommerce platform.
According to the gql playground there is a mutation to do so that takes a CheckoutCreateInput object as it's argument.
Here is an example mutation that works fine within the playground.
Here is the current code that I have tried (I am doing this within a vuex action)
export const actions = {
addToCart({ commit, dispatch }, cartItem) {
const currentCartItems = this.state.cartItems
// Check to see if we already have a checkout object
if (this.state.checkoutId !== '') {
// Create a new checkout ID
console.log('creating new checkout object')
try {
this.app.apolloProvider.defaultClient
.mutate({
mutation: CREATE_CART_MUTATION,
variables: {
checkoutInput: {
lines: { quantity: 10, variantId: 'UHJvZHVjdFZhcmlhbnQ6NQ==' },
email: 'test#test.com'
}
}
})
.then(({ data }) => {
console.log(data)
})
} catch (e) {
console.log(e)
}
} else {
console.log('checkout id already set')
}
// TODO: Check to see if the cart already contains the current Cart Item
commit('ADD_CART_ITEM', cartItem)
}
and here is the CREATE_CART_MUTATION:
import gql from 'graphql-tag'
export const CREATE_CART_MUTATION = gql`
mutation($checkoutInput: CheckoutCreateInput!) {
checkoutCreate(input: $checkoutInput) {
checkout {
id
created
lastChange
lines {
id
variant {
id
name
}
quantity
totalPrice {
gross {
localized
}
net {
localized
}
}
}
totalPrice {
gross {
localized
}
net {
localized
}
}
}
}
}
`
On the server this comes back with the following error:
graphql.error.base.GraphQLError: Variable "$checkoutInput" got invalid value {"email": "test#test.com", "lines": {"quantity": 10, "variantId": "UHJvZHVjdFZhcmlhbnQ6NQ=="}}.
In field "lines": In element #0: Expected "CheckoutLineInput", found not an object.
Looks like I was most of the way there, I was just passing a single lines object rather than an array of them. The correct code is as follows:
try {
this.app.apolloProvider.defaultClient
.mutate({
mutation: CREATE_CART_MUTATION,
variables: {
checkoutInput: {
lines: [
{ quantity: cartItem.quantity, variantId: cartItem.variantId }
],
email: 'test#test.com'
}
}
})
.then(({ data }) => {
console.log('mutation done!')
commit('SET_CHECKOUT_OBJECT', data.checkoutCreate.checkout)
})
} catch (e) {
console.log('error:')
console.log(e)
}
I want to use the $push method to push an object into a nested array. But i cant get it to work that you can dynamically get the right object inside of the array. Let me explain better by showing the code.
This is my Schema:
var StartedRaceSchema = new mongoose.Schema({
waypoints: {
type: Object,
name: String,
check_ins: {
type: Object,
user: {
type: Object,
ref: 'User'
}
}
}
});
When you check in on a waypoint, it has to be pushed in the correct waypoints nested Check_ins
This is the code for the update:
StartedRace.findByIdAndUpdate(req.params.id,
{ $push: { 'waypoints.1.check_ins': req.body.user } },
function (error) {
if (error) {
console.log(error)
res.send({
success: false,
error: error
})
} else {
res.send({
success: true
})
}
}
)
As you can see i can only get it to work with fields like:
'waypoints.1.check_ins'
That 1 needs to be dynamically because it gets send within the parameters.
But i can not get it to work dynamically, only hard coded.
Does anyone know how to do this?
Populate the collection with a list of check_ins enumerated by their ids.
waypoints.check_ins = {
...waypoints.check_ins,
[response.id]: response
}
You'd then have a list of check_ins that can referenced by their ids.
You could try this syntax instead of the dot notation:
let id = req.params.id;
StartedRace.findByIdAndUpdate(req.params.id,
{ $push: { waypoints: { id: { check_ins: req.body.user } } } }, { new : true } )
.exec()
.then(race => console.log(race))
.catch(err => err);
I used a Promise, but it's the same with a callback.
I am using vue-head in website because of I have to pass the name of the program to the html head, and the inf. it is coming from an API, so I make the request but every time I try to pass the name it send me error this the code:
export default {
data: () => ({
errors: [],
programs: [],
firstVideo: {},
vidProgram: {}
}),
},
created() {
//do something after creating vue instance
this.api = new ApiCanal({})
this.getProgram()
},
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.firstVideo = response.data[0]
this.vidProgram = response.data[0]['program']
})
.catch(error => {
this.errors = error
});
}
},
head: {
//this is the inf. for the head
title: {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
}
}
}
I will really appreciate if you can help me with this issue
If you want to use properties of your Vue object/component in the title there, you need to make it a function, as currently this refers to the object creating your Vue component (probably the global window object).
head: {
title: function() {
return {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
};
}
}