Queries
In GraphQL, a query is a request made to the API to retrieve data. It is represented with a GraphQL document like this:
query myHelloQueryName {
hello
}
In the apollo
object, add an attribute for each property you want to feed with the result of an Apollo query. Each one of them will become a Smart Query.
Smart Queries are wrappers around GraphQL queries with additional features like automatic reactivity.
Simple query
Use gql
to write your GraphQL queries:
import gql from 'graphql-tag'
Put the gql query directly as the value:
apollo: {
// Simple query that will update the 'hello' vue property
hello: gql`query {
hello
}`,
},
You can then access the smart query with this.$apollo.queries.<name>
.
You can initialize the property in your vue component's data
hook:
data () {
return {
// Initialize your apollo data
hello: '',
},
},
Server-side, add the corresponding schema and resolver:
export const schema = `
type Query {
hello: String
}
schema {
query: Query
}
`
export const resolvers = {
Query: {
hello (root, args, context) {
return 'Hello world!'
},
},
}
For more info, visit the apollo doc.
You can then use your property as usual in your vue component:
<template>
<div class="apollo">
<h3>Hello</h3>
<p>
{{hello}}
</p>
</div>
</template>
Name matching
Please note that a common beginner's mistake is to use a data name different from the field name in the query, e.g.:
apollo: {
world: gql`query {
hello
}`
}
Notice how world
is different from hello
; vue-apollo
won't guess which data you want to put in the component from the query result. By default, it will just try the name you are using for the data in the component (which is the key in the apollo
object), in this case world
. If the names don't match, you can use update
option to tell vue-apollo
what to use as data from the result:
apollo: {
world: {
query: gql`query {
hello
}`,
update: data => data.hello
}
}
You can also rename the field in the GraphQL document directly:
apollo: {
world: gql`query {
world: hello
}`
}
In this example, we rename the hello
field to world
so that vue-apollo
can automatically infer what should be retrieved from the result.
Query with parameters
You can add variables (and other parameters) to your gql
query by declaring query
and variables
in an object instead of just the GraphQL query:
// Apollo-specific options
apollo: {
// Query with parameters
ping: {
// gql query
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Static parameters
variables: {
message: 'Meow',
},
},
},
You can use the apollo watchQuery
options in the object, like:
fetchPolicy
pollInterval
- ...
See the apollo doc for more details.
For example, you could add the fetchPolicy
apollo option like this:
apollo: {
// Query with parameters
ping: {
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
variables: {
message: 'Meow'
},
// Additional options here
fetchPolicy: 'cache-and-network',
},
},
Again, you can initialize your property in your vue component:
data () {
return {
// Initialize your apollo data
ping: '',
}
},
Server-side, add the corresponding schema and resolver:
export const schema = `
type Query {
ping(message: String!): String
}
schema {
query: Query
}
`
export const resolvers = {
Query: {
ping (root, { message }, context) {
return `Answering ${message}`
},
},
}
And then use it in your vue component:
<template>
<div class="apollo">
<h3>Ping</h3>
<p>
{{ ping }}
</p>
</div>
</template>
Reactive parameters
Use a function instead to make the parameters reactive with vue properties:
// Apollo-specific options
apollo: {
// Query with parameters
ping: {
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Reactive parameters
variables () {
// Use vue reactive properties here
return {
message: this.pingInput,
}
},
},
},
This will re-fetch the query each time a parameter changes, for example:
<template>
<div class="apollo">
<h3>Ping</h3>
<input v-model="pingInput" placeholder="Enter a message" />
<p>
{{ping}}
</p>
</div>
</template>
Loading state
You can display a loading state thanks to the $apollo.loading
prop:
<div v-if="$apollo.loading">Loading...</div>
Or for this specific ping
query:
<div v-if="$apollo.queries.ping.loading">Loading...</div>
Option function
You can use a function which will be called once when the component is created and it must return the option object:
// Apollo-specific options
apollo: {
// Query with parameters
ping () {
// This is called once when the component is created
// It must return the option object
return {
// gql query
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Static parameters
variables: {
message: 'Meow',
},
}
},
},
TIP
This also works for subscriptions.
Reactive query definition
You can use a function for the query
option. This will update the graphql query definition automatically:
// The featured tag can be either a random tag or the last added tag
featuredTag: {
query () {
// Here you can access the component instance with 'this'
if (this.showTag === 'random') {
return gql`{
randomTag {
id
label
type
}
}`
} else if (this.showTag === 'last') {
return gql`{
lastTag {
id
label
type
}
}`
}
},
// We need this to assign the value of the 'featuredTag' component property
update: data => data.randomTag || data.lastTag,
},
TIP
This also works for subscriptions.
Skipping the query
If the query is skipped, it will disable it and the result will not be updated anymore. You can use the skip
option:
// Apollo-specific options
apollo: {
tags: {
// GraphQL Query
query: gql`query tagList ($type: String!) {
tags(type: $type) {
id
label
}
}`,
// Reactive variables
variables () {
return {
type: this.type,
}
},
// Disable the query
skip () {
return this.skipQuery
},
},
},
Here, skip
will be called automatically when the skipQuery
component property changes.
You can also access the query directly and set the skip
property:
this.$apollo.queries.tags.skip = true
If the query skip
becomes false
, the query will automatically execute again.
Reactive Query Example
Here is a reactive query example using polling:
// Apollo-specific options
apollo: {
// 'tags' data property on vue instance
tags: {
query: gql`query tagList {
tags {
id,
label
}
}`,
pollInterval: 300, // ms
},
},
Here is how the server-side looks like:
export const schema = `
type Tag {
id: Int
label: String
}
type Query {
tags: [Tag]
}
schema {
query: Query
}
`
// Fake word generator
import casual from 'casual'
// Let's generate some tags
var id = 0
var tags = []
for (let i = 0; i < 42; i++) {
addTag(casual.word)
}
function addTag (label) {
let t = {
id: id++,
label,
}
tags.push(t)
return t
}
export const resolvers = {
Query: {
tags(root, args, context) {
return tags
},
},
}
Manually adding a smart Query
You can manually add a smart query with the $apollo.addSmartQuery(key, options)
method:
created () {
this.$apollo.addSmartQuery('comments', {
// Same options like above
})
}
TIP
Internally, this method is called for each query entry in the component apollo
option.
Advanced options
There are even more options specific to vue-apollo, see the API Reference.