Skip to content

Queries

In GraphQL, a query is a request made to the API to retrieve data. It is represented with a GraphQL document like this:

graphql
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:

js
import gql from 'graphql-tag'

Put the gql query directly as the value:

js
export default {
  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:

js
export default {
  data() {
    return {
    // Initialize your apollo data
      hello: '',
    }
  },
}

Server-side, add the corresponding schema and resolver:

js
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:

vue
<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.:

js
export default {
  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:

js
export default {
  apollo: {
    world: {
      query: gql`query {
      hello
    }`,
      update: data => data.hello
    }
  }
}

You can also rename the field in the GraphQL document directly:

js
export default {
  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:

js
export default {
// 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:

js
export default {
  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:

js
export default {
  data() {
    return {
    // Initialize your apollo data
      ping: '',
    }
  },
}

Server-side, add the corresponding schema and resolver:

js
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:

vue
<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:

js
export default {
// 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:

vue
<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:

vue
<div v-if="$apollo.loading">Loading...</div>

Or for this specific ping query:

vue
<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:

js
export default {
// 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:

js
export default {
  apollo: {
    // 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:

js
export default {
// 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:

js
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:

js
export default {
// 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:

js
// Fake word generator
import casual from 'casual'

export const schema = `
type Tag {
  id: Int
  label: String
}

type Query {
  tags: [Tag]
}

schema {
  query: Query
}
`

// Let's generate some tags
let id = 0
const tags = []
for (let i = 0; i < 42; i++) {
  addTag(casual.word)
}

function addTag(label) {
  const 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:

js
export default {
  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.

Released under the MIT License.