Breaking api change -> use only watchQuery

This commit is contained in:
Guillaume Chau
2016-09-20 01:50:40 +02:00
parent 7f8fc7a46e
commit ab7c021ccb
3 changed files with 118 additions and 164 deletions
+91 -117
View File
@@ -18,6 +18,7 @@ import Vue from 'vue';
import ApolloClient, { createNetworkInterface, addTypename } from './apollo-client';
import VueApollo from 'vue-apollo';
// Create the apollo client
const apolloClient = new ApolloClient({
networkInterface: createNetworkInterface({
uri: 'http://localhost:8080/graphql',
@@ -26,6 +27,7 @@ const apolloClient = new ApolloClient({
queryTransformer: addTypename,
});
// Install the vue plugin
Vue.use(VueApollo, {
apolloClient,
});
@@ -47,7 +49,7 @@ You can access the [apollo-client](http://dev.apollodata.com/core/apollo-client-
### Queries
In the `query` object, add an attribute for each property you want to feed with the result of an Apollo query.
In the `apollo` object, add an attribute for each property you want to feed with the result of an Apollo query.
#### Simple query
@@ -61,11 +63,8 @@ Put the [gql](http://docs.apollostack.com/apollo-client/core.html#gql) query dir
```javascript
apollo: {
// Non-reactive query
query: {
// Simple query that will update the 'hello' vue property
hello: gql`{hello}`,
},
// Simple query that will update the 'hello' vue property
hello: gql`{hello}`,
},
```
@@ -133,46 +132,43 @@ You can add variables (read parameters) to your `gql` query by declaring `query`
```javascript
// Apollo-specific options
apollo: {
// Non-reactive query
query: {
// Query with parameters
ping: {
// gql query
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Static parameters
variables: {
message: 'Meow',
},
// 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 options in the object, like:
You can use the apollo `watchQuery` options in the object, like:
- `forceFetch`
- `fragments`
- `returnPartialData`
- `pollInterval`
- ...
See the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.query) for more details.
See the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.watchQuery) for more details.
For example, you could add the `forceFetch` apollo option like this:
```javascript
apollo: {
query: {
// Query with parameters
ping: {
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
variables: {
message: 'Meow'
},
// Additional options here
forceFetch: true,
// Query with parameters
ping: {
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
variables: {
message: 'Meow'
},
// Additional options here
forceFetch: true,
},
},
```
@@ -239,20 +235,17 @@ Use a function instead to make the parameters reactive with vue properties:
```javascript
// Apollo-specific options
apollo: {
// Non-reactive query
query: {
// 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,
};
},
// 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,
};
},
},
},
@@ -285,51 +278,48 @@ These are the available advanced options you can use:
```javascript
// Apollo-specific options
apollo: {
// Non-reactive query
query: {
// Advanced query with parameters
// The 'variables' method is watched by vue
pingMessage: {
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Reactive parameters
variables() {
// Use vue reactive properties here
return {
message: this.pingInput,
};
},
// We use a custom update callback because
// the field names don't match
// By default, the 'pingMessage' attribute
// would be used on the 'data' result object
// Here we know the result is in the 'ping' attribute
// considering the way the apollo server works
update(data) {
console.log(data);
// The returned value will update
// the vue property 'pingMessage'
return data.ping;
},
// Optional result hook
result(data) {
console.log("We got some result!");
},
// Error handling
error(error) {
console.error('We\'ve got an error!', error);
},
// Loading state
// loadingKey is the name of the data property
// that will be incremented when the query is loading
// and decremented when it no longer is.
loadingKey: 'loadingQueriesCount',
// watchLoading will be called whenever the loading state changes
watchLoading(isLoading, countModifier) {
// isLoading is a boolean
// countModifier is either 1 or -1
},
// Advanced query with parameters
// The 'variables' method is watched by vue
pingMessage: {
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Reactive parameters
variables() {
// Use vue reactive properties here
return {
message: this.pingInput,
};
},
// We use a custom update callback because
// the field names don't match
// By default, the 'pingMessage' attribute
// would be used on the 'data' result object
// Here we know the result is in the 'ping' attribute
// considering the way the apollo server works
update(data) {
console.log(data);
// The returned value will update
// the vue property 'pingMessage'
return data.ping;
},
// Optional result hook
result(data) {
console.log("We got some result!");
},
// Error handling
error(error) {
console.error('We\'ve got an error!', error);
},
// Loading state
// loadingKey is the name of the data property
// that will be incremented when the query is loading
// and decremented when it no longer is.
loadingKey: 'loadingQueriesCount',
// watchLoading will be called whenever the loading state changes
watchLoading(isLoading, countModifier) {
// isLoading is a boolean
// countModifier is either 1 or -1
},
},
},
@@ -341,42 +331,26 @@ If you use `ES2015`, you can also write the `update` like this:
update: data => data.ping
```
### Reactive Queries
### Reactive Query Example
For more info, see the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.watchQuery).
Add your queries in a `watchQuery` object instead of `data`:
Here is a reactive query example using polling:
```javascript
// Apollo-specific options
apollo: {
// Reactive query
watchQuery: {
// 'tags' data property on vue instance
tags: {
query: gql`query tagList {
tags {
id,
label
}
}`,
pollInterval: 300, // ms
},
// 'tags' data property on vue instance
tags: {
query: gql`query tagList {
tags {
id,
label
}
}`,
pollInterval: 300, // ms
},
},
```
You can use the apollo options, for example:
- `forceFetch`
- `returnPartialData`
- `pollInterval`
- `fragments`
- ...
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`.
Here is how the server-side looks like:
```javascript
+26 -46
View File
@@ -32,22 +32,17 @@ class DollarApollo {
return this.client.mutate;
}
option(key, options, watch) {
option(key, options) {
const vm = this.vm;
const $apollo = this;
let query, observer, sub;
let simpleQuery = false;
let firstLoadingDone = false;
let loadingKey = options.loadingKey;
let loadingChangeCb = options.watchLoading;
if (options.pollInterval) {
watch = true;
}
if (typeof loadingChangeCb === 'function') {
loadingChangeCb = loadingChangeCb.bind(vm);
}
@@ -55,7 +50,6 @@ class DollarApollo {
// Simple query
if (!options.query) {
query = options;
simpleQuery = true;
}
function generateApolloOptions(variables) {
@@ -75,38 +69,24 @@ class DollarApollo {
function q(variables) {
applyLoadingModifier(1);
if (simpleQuery) {
$apollo.query({
query
}).then(nextResult).catch(catchError);
} else if (watch) {
if (options.forceFetch && observer) {
// Refresh query
observer.refetch(variables, {
forceFetch: !!options.forceFetch
});
} else {
if (sub) {
sub.unsubscribe();
}
// Create observer
observer = $apollo.watchQuery(generateApolloOptions(variables));
// Create subscription
sub = observer.subscribe({
next: nextResult,
error: catchError
});
if (options.forceFetch && observer) {
// Refresh query
observer.refetch(variables, {
forceFetch: !!options.forceFetch
});
} else {
if (sub) {
sub.unsubscribe();
}
} else {
$apollo.query(generateApolloOptions(variables)).then(nextResult).catch(catchError);
// Create observer
observer = $apollo.watchQuery(generateApolloOptions(variables));
// Create subscription
sub = observer.subscribe({
next: nextResult,
error: catchError
});
}
}
@@ -186,18 +166,18 @@ function prepare() {
let apollo = this.$options.apollo;
if (apollo) {
// One-time queries with $query(), called each time a Vue dependency is updated (using $watch)
if (apollo.query) {
for (let key in apollo.query) {
this.$apollo.option(key, apollo.query[key], false);
}
const queries = omit(apollo, [
'subscribe',
]);
// watchQuery
for (let key in queries) {
this.$apollo.option(key, queries[key]);
}
// Auto updating queries with $watchQuery(), re-called each time a Vue dependency is updated (using $watch)
if (apollo.watchQuery) {
for (let key in apollo.watchQuery) {
this.$apollo.option(key, apollo.watchQuery[key], true);
}
// subscribe
if (apollo.subscribe) {
// TODO
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vue-apollo",
"version": "1.0.0-beta5",
"version": "1.0.0-beta6",
"description": "Vue apollo integration",
"main": "index.js",
"scripts": {