API update, Readme
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
|
||||
Integrates [apollo](http://www.apollostack.com/) in your vue components with declarative queries.
|
||||
|
||||
[See a simple Apollo server example](https://github.com/Akryum/apollo-server-example)
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
npm install vue-apollo
|
||||
npm install --save vue-apollo apollo-client
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -13,11 +15,15 @@ Integrates [apollo](http://www.apollostack.com/) in your vue components with dec
|
||||
|
||||
```javascript
|
||||
import Vue from 'vue';
|
||||
import ApolloClient from 'apollo-client';
|
||||
import VueApollo from 'vue-apollo'
|
||||
import ApolloClient, { createNetworkInterface, addTypename } from './apollo-client';
|
||||
import VueApollo from 'vue-apollo';
|
||||
|
||||
const apolloClient = new ApolloClient({
|
||||
/* ... */
|
||||
networkInterface: createNetworkInterface({
|
||||
uri: 'http://localhost:8080/graphql',
|
||||
transportBatching: true,
|
||||
}),
|
||||
queryTransformer: addTypename,
|
||||
});
|
||||
|
||||
Vue.use(VueApollo, {
|
||||
@@ -33,28 +39,34 @@ To declare apollo queries in your Vue component, add an `apollo` object :
|
||||
new Vue({
|
||||
apollo: {
|
||||
// Apollo specific options
|
||||
}
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
You can access the [apollo-client](http://docs.apollostack.com/apollo-client/index.html) instance with `this.$apollo.client` in all your vue components.
|
||||
You can access the [apollo-client](http://dev.apollodata.com/core/apollo-client-api.html) instance with `this.$apollo.client` in all your vue components.
|
||||
|
||||
### Queries
|
||||
|
||||
In the `data` object, add an attribute for each property you want to feed with the result of an Apollo query.
|
||||
In the `query` object, add an attribute for each property you want to feed with the result of an Apollo query.
|
||||
|
||||
#### Simple query
|
||||
|
||||
Use `gql` to write your GraphQL queries:
|
||||
|
||||
```javascript
|
||||
import gql from 'graphql-tag';
|
||||
```
|
||||
|
||||
Put the [gql](http://docs.apollostack.com/apollo-client/core.html#gql) query directly as the value:
|
||||
|
||||
```javascript
|
||||
apollo: {
|
||||
// Non-reactive query
|
||||
data: {
|
||||
query: {
|
||||
// Simple query that will update the 'hello' vue property
|
||||
hello: gql`{hello}`
|
||||
}
|
||||
}
|
||||
hello: gql`{hello}`,
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
Don't forget to initialize your property in your vue component:
|
||||
@@ -63,9 +75,18 @@ Don't forget to initialize your property in your vue component:
|
||||
data () {
|
||||
return {
|
||||
// Initialize your apollo data
|
||||
hello: ''
|
||||
}
|
||||
}
|
||||
hello: '',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
Or with the `ES2015` syntax:
|
||||
|
||||
```javascript
|
||||
data: () => ({
|
||||
// Initialize your apollo data
|
||||
hello: '',
|
||||
}),
|
||||
```
|
||||
|
||||
Server-side, add the corresponding schema and resolver:
|
||||
@@ -85,12 +106,12 @@ export const resolvers = {
|
||||
Query: {
|
||||
hello(root, args, context) {
|
||||
return "Hello world!";
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
For more info, visit the [apollo doc](http://docs.apollostack.com/apollo-server/index.html).
|
||||
For more info, visit the [apollo doc](http://dev.apollodata.com/tools/).
|
||||
|
||||
You can then use your property as usual in your vue component:
|
||||
|
||||
@@ -113,7 +134,7 @@ You can add variables (read parameters) to your `gql` query by declaring `query`
|
||||
// Apollo-specific options
|
||||
apollo: {
|
||||
// Non-reactive query
|
||||
data: {
|
||||
query: {
|
||||
// Query with parameters
|
||||
ping: {
|
||||
// gql query
|
||||
@@ -122,24 +143,25 @@ apollo: {
|
||||
}`,
|
||||
// Static parameters
|
||||
variables: {
|
||||
message: 'Meow'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message: 'Meow',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
You can use the following apollo options in the object:
|
||||
You can use the apollo options in the object, like:
|
||||
- `forceFetch`
|
||||
- `fragments`
|
||||
- ...
|
||||
|
||||
See the [apollo doc](http://docs.apollostack.com/apollo-client/queries.html#query) for more details.
|
||||
See the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.query) for more details.
|
||||
|
||||
For example, you could add the `forceFetch` apollo option like this:
|
||||
|
||||
```javascript
|
||||
apollo: {
|
||||
data: {
|
||||
query: {
|
||||
// Query with parameters
|
||||
ping: {
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
@@ -149,10 +171,10 @@ apollo: {
|
||||
message: 'Meow'
|
||||
},
|
||||
// Additional options here
|
||||
forceFetch: true
|
||||
}
|
||||
}
|
||||
}
|
||||
forceFetch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
Don't forget to initialize your property in your vue component:
|
||||
@@ -161,9 +183,18 @@ Don't forget to initialize your property in your vue component:
|
||||
data () {
|
||||
return {
|
||||
// Initialize your apollo data
|
||||
ping: ''
|
||||
}
|
||||
}
|
||||
ping: '',
|
||||
};
|
||||
},
|
||||
```
|
||||
|
||||
Or with the `ES2015` syntax:
|
||||
|
||||
```javascript
|
||||
data: () => ({
|
||||
// Initialize your apollo data
|
||||
ping: '',
|
||||
}),
|
||||
```
|
||||
|
||||
Server-side, add the corresponding schema and resolver:
|
||||
@@ -183,8 +214,8 @@ export const resolvers = {
|
||||
Query: {
|
||||
ping(root, { message }, context) {
|
||||
return `Answering ${message}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -209,7 +240,7 @@ Use a function instead to make the parameters reactive with vue properties:
|
||||
// Apollo-specific options
|
||||
apollo: {
|
||||
// Non-reactive query
|
||||
data: {
|
||||
query: {
|
||||
// Query with parameters
|
||||
ping: {
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
@@ -219,12 +250,12 @@ apollo: {
|
||||
variables() {
|
||||
// Use vue reactive properties here
|
||||
return {
|
||||
message: this.pingInput
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message: this.pingInput,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
This will re-fetch the query each time a parameter changes, for example:
|
||||
@@ -255,7 +286,7 @@ These are the available advanced options you can use:
|
||||
// Apollo-specific options
|
||||
apollo: {
|
||||
// Non-reactive query
|
||||
data: {
|
||||
query: {
|
||||
// Advanced query with parameters
|
||||
// The 'variables' method is watched by vue
|
||||
pingMessage: {
|
||||
@@ -266,8 +297,8 @@ apollo: {
|
||||
variables() {
|
||||
// Use vue reactive properties here
|
||||
return {
|
||||
message: this.pingInput
|
||||
}
|
||||
message: this.pingInput,
|
||||
};
|
||||
},
|
||||
// We use a custom update callback because
|
||||
// the field names don't match
|
||||
@@ -298,13 +329,13 @@ apollo: {
|
||||
watchLoading(isLoading, countModifier) {
|
||||
// isLoading is a boolean
|
||||
// countModifier is either 1 or -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
If you use ES2015, you can also write the `update` like this:
|
||||
If you use `ES2015`, you can also write the `update` like this:
|
||||
|
||||
```javascript
|
||||
update: data => data.ping
|
||||
@@ -312,29 +343,27 @@ update: data => data.ping
|
||||
|
||||
### Reactive Queries
|
||||
|
||||
*For now, the reactivity in apollo is quite limited, since you can only do polling.*
|
||||
For more info, see the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.watchQuery).
|
||||
|
||||
For more info, see the [apollo doc](http://docs.apollostack.com/apollo-client/core.html#watchQuery).
|
||||
|
||||
Add your queries in a `watch` object instead of `data`:
|
||||
Add your queries in a `watchQuery` object instead of `data`:
|
||||
|
||||
```javascript
|
||||
// Apollo-specific options
|
||||
apollo: {
|
||||
// Reactive query
|
||||
watch: {
|
||||
watchQuery: {
|
||||
// 'tags' data property on vue instance
|
||||
tags: {
|
||||
query: gql`{
|
||||
query: gql`query tagList {
|
||||
tags {
|
||||
id,
|
||||
label
|
||||
}
|
||||
}`,
|
||||
pollInterval: 300 // ms
|
||||
}
|
||||
}
|
||||
}
|
||||
pollInterval: 300, // ms
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
You can use the apollo options, for example:
|
||||
@@ -342,8 +371,9 @@ You can use the apollo options, for example:
|
||||
- `returnPartialData`
|
||||
- `pollInterval`
|
||||
- `fragments`
|
||||
- ...
|
||||
|
||||
See the [apollo doc](http://docs.apollostack.com/apollo-client/queries.html#watchQuery) for more details.
|
||||
See the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.watchQuery) for more details.
|
||||
|
||||
You can also use the advanced options detailed above, like `result` or `watchLoading`.
|
||||
|
||||
@@ -378,7 +408,7 @@ for (let i = 0; i < 42; i++) {
|
||||
function addTag(label) {
|
||||
let t = {
|
||||
id: id++,
|
||||
label
|
||||
label,
|
||||
};
|
||||
tags.push(t);
|
||||
return t;
|
||||
@@ -388,41 +418,70 @@ export const resolvers = {
|
||||
Query: {
|
||||
tags(root, args, context) {
|
||||
return tags;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Mutations
|
||||
|
||||
Mutations are queries that changes your data state on your apollo server. For more info, visit the [apollo doc](http://docs.apollostack.com/apollo-client/core.html#Mutations).
|
||||
Mutations are queries that changes your data state on your apollo server. For more info, visit the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.mutate).
|
||||
|
||||
```javascript
|
||||
methods: {
|
||||
addTag() {
|
||||
// Mutate the tags data
|
||||
// You can also use this.$apollo.client.mutate
|
||||
// We save the user input in case of an error
|
||||
const newTag = this.newTag;
|
||||
// We clear it early to give the UI a snappy feel
|
||||
this.newTag = '';
|
||||
// Call to the graphql mutation
|
||||
this.$apollo.mutate({
|
||||
mutation: gql`mutation AddTag($label: String!) {
|
||||
// Query
|
||||
mutation: gql`mutation ($label: String!) {
|
||||
addTag(label: $label) {
|
||||
id,
|
||||
id
|
||||
label
|
||||
}
|
||||
}`,
|
||||
// Parameters
|
||||
variables: {
|
||||
label: this.tagLabel
|
||||
}
|
||||
label: newTag,
|
||||
},
|
||||
// Update the cache with the result
|
||||
// 'tagList' is the name of the query declared before
|
||||
// that will be updated with the optimistic response
|
||||
// and the result of the mutation
|
||||
updateQueries: {
|
||||
tagList: (previousQueryResult, { mutationResult }) => {
|
||||
// We incorporate any received result (either optimistic or real)
|
||||
// into the 'tagList' query we set up earlier
|
||||
return {
|
||||
tags: [...previousQueryResult.tags, mutationResult.data.addTag],
|
||||
};
|
||||
},
|
||||
},
|
||||
// Optimistic UI
|
||||
// Will be treated as a 'fake' result as soon as the request is made
|
||||
// so that the UI can react quickly and the user be happy
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
addTag: {
|
||||
__typename: 'Tag',
|
||||
id: -1,
|
||||
label: newTag,
|
||||
},
|
||||
},
|
||||
}).then((data) => {
|
||||
// Result
|
||||
console.log(data);
|
||||
this.tagLabel = '';
|
||||
}).catch((error) => {
|
||||
// Error
|
||||
console.error(error);
|
||||
// We restore the initial user input
|
||||
this.newTag = newTag;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
Server-side:
|
||||
@@ -461,7 +520,7 @@ for (let i = 0; i < 42; i++) {
|
||||
function addTag(label) {
|
||||
let t = {
|
||||
id: id++,
|
||||
label
|
||||
label,
|
||||
};
|
||||
tags.push(t);
|
||||
return t;
|
||||
@@ -471,14 +530,14 @@ export const resolvers = {
|
||||
Query: {
|
||||
tags(root, args, context) {
|
||||
return tags;
|
||||
}
|
||||
},
|
||||
},
|
||||
Mutation: {
|
||||
addTag(root, { label }, context) {
|
||||
console.log(`adding tag '${label}'`);
|
||||
return addTag(label);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
+8
-8
@@ -1,4 +1,4 @@
|
||||
import _ from 'lodash';
|
||||
import omit from 'lodash.omit';
|
||||
|
||||
let apolloClient = null;
|
||||
|
||||
@@ -59,7 +59,7 @@ class DollarApollo {
|
||||
}
|
||||
|
||||
function generateApolloOptions(variables) {
|
||||
const apolloOptions = _.omit(options, [
|
||||
const apolloOptions = omit(options, [
|
||||
'variables',
|
||||
'watch',
|
||||
'update',
|
||||
@@ -187,16 +187,16 @@ function prepare() {
|
||||
|
||||
if (apollo) {
|
||||
// One-time queries with $query(), called each time a Vue dependency is updated (using $watch)
|
||||
if (apollo.data) {
|
||||
for (let key in apollo.data) {
|
||||
this.$apollo.option(key, apollo.data[key], false);
|
||||
if (apollo.query) {
|
||||
for (let key in apollo.query) {
|
||||
this.$apollo.option(key, apollo.query[key], false);
|
||||
}
|
||||
}
|
||||
|
||||
// Auto updating queries with $watchQuery(), re-called each time a Vue dependency is updated (using $watch)
|
||||
if (apollo.watch) {
|
||||
for (let key in apollo.watch) {
|
||||
this.$apollo.option(key, apollo.watch[key], true);
|
||||
if (apollo.watchQuery) {
|
||||
for (let key in apollo.watchQuery) {
|
||||
this.$apollo.option(key, apollo.watchQuery[key], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-apollo",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.0-beta1",
|
||||
"description": "Vue apollo integration",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"url": "https://github.com/Akryum/vue-apollo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Akryum/vue-apollo#readme",
|
||||
"dependencies": {
|
||||
"lodash": "^4.15.0"
|
||||
"peerDependencies": {
|
||||
"apollo-client": "^0.4.15"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user