diff --git a/CHANGELOG.md b/CHANGELOG.md
index 39632f3fc..6edc8e6d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
### vNEXT
- Added `ApolloModule` (with RC5 of Angular2 comes NgModules) ([PR #63](https://github.com/apollostack/angular2-apollo/pull/63))
+- Added ability to use query variables as observables. With this, the query can be automatically re-run when those obserables emit new values. ([PR #64]((https://github.com/apollostack/angular2-apollo/pull/64)))
### v0.4.2
diff --git a/examples/hello-world/client/imports/app.component.html b/examples/hello-world/client/imports/app.component.html
index 32ac6d206..41fe87369 100644
--- a/examples/hello-world/client/imports/app.component.html
+++ b/examples/hello-world/client/imports/app.component.html
@@ -7,7 +7,7 @@
Add new
List
-
+
diff --git a/examples/hello-world/client/imports/app.component.ts b/examples/hello-world/client/imports/app.component.ts
index e8adeb895..1618a12ec 100644
--- a/examples/hello-world/client/imports/app.component.ts
+++ b/examples/hello-world/client/imports/app.component.ts
@@ -1,11 +1,15 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, AfterViewInit } from '@angular/core';
+import { FormControl } from '@angular/forms';
import { Angular2Apollo, ApolloQueryPipe, ApolloQueryObservable } from 'angular2-apollo';
import { ApolloQueryResult } from 'apollo-client';
+import { Subject } from 'rxjs/Subject';
import { User } from './user.interface';
import gql from 'graphql-tag';
+import 'rxjs/add/operator/debounceTime';
+
import template from './app.component.html';
interface Data {
@@ -17,15 +21,16 @@ interface Data {
template,
pipes: [ApolloQueryPipe],
})
-export class AppComponent implements OnInit {
- data: ApolloQueryObservable;
- firstName: string;
- lastName: string;
- nameFilter: string;
+export class AppComponent implements OnInit, AfterViewInit {
+ public data: ApolloQueryObservable;
+ public firstName: string;
+ public lastName: string;
+ public nameControl = new FormControl();
+ public nameFilter: Subject = new Subject();
constructor(private angular2Apollo: Angular2Apollo) {}
- ngOnInit() {
+ public ngOnInit() {
this.data = this.angular2Apollo.watchQuery({
query: gql`
query getUsers($name: String) {
@@ -43,9 +48,17 @@ export class AppComponent implements OnInit {
name: this.nameFilter,
},
});
+
+ this.nameControl.valueChanges.debounceTime(300).subscribe(name => {
+ this.nameFilter.next(name);
+ });
+ }
+
+ public ngAfterViewInit() {
+ this.nameFilter.next(null);
}
- newUser(firstName: string) {
+ public newUser(firstName: string) {
this.angular2Apollo.mutate({
mutation: gql`
mutation addUser(
diff --git a/examples/hello-world/client/imports/app.module.ts b/examples/hello-world/client/imports/app.module.ts
index 650da81e4..141befbd1 100644
--- a/examples/hello-world/client/imports/app.module.ts
+++ b/examples/hello-world/client/imports/app.module.ts
@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
-import { FormsModule } from '@angular/forms';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ApolloModule } from 'angular2-apollo';
import { AppComponent } from './app.component';
@@ -11,6 +11,7 @@ import { client } from './client';
imports: [
BrowserModule,
FormsModule,
+ ReactiveFormsModule,
ApolloModule.withClient(client),
],
bootstrap: [ AppComponent ],
diff --git a/global.d.ts b/global.d.ts
index 2a59d31e0..4374c0b98 100644
--- a/global.d.ts
+++ b/global.d.ts
@@ -12,3 +12,8 @@ declare module 'lodash.assign' {
import main = require('~lodash/index');
export = main.assign;
}
+
+declare module 'lodash.omit' {
+ import main = require('~lodash/index');
+ export = main.omit;
+}
diff --git a/package.json b/package.json
index e2081ba67..df456af00 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,8 @@
"dependencies": {
"lodash.assign": "^4.0.9",
"lodash.forin": "^4.2.0",
- "lodash.isequal": "^4.2.0"
+ "lodash.isequal": "^4.2.0",
+ "lodash.omit": "^4.4.1"
},
"devDependencies": {
"@angular/common": "^2.0.0-rc.5",
diff --git a/src/angular2Apollo.ts b/src/angular2Apollo.ts
index 32eaae074..0cf121200 100644
--- a/src/angular2Apollo.ts
+++ b/src/angular2Apollo.ts
@@ -8,10 +8,23 @@ import {
Inject,
} from '@angular/core';
+import 'rxjs/add/operator/switchMap';
+
+import assign = require('lodash.assign');
+import omit = require('lodash.omit');
+
import {
ApolloQueryObservable,
} from './apolloQueryObservable';
+import {
+ ObservableQueryRef,
+} from './utils/observableQuery';
+
+import {
+ observeVariables,
+} from './utils/observeVariables';
+
export const angularApolloClient = new OpaqueToken('AngularApolloClient');
export const defaultApolloClient = (client: ApolloClient): Provider => {
return provide(angularApolloClient, {
@@ -23,12 +36,29 @@ export const defaultApolloClient = (client: ApolloClient): Provider => {
export class Angular2Apollo {
constructor(
@Inject(angularApolloClient) private client: any
- ) {
-
- }
+ ) {}
public watchQuery(options): ApolloQueryObservable {
- return new ApolloQueryObservable(this.client.watchQuery(options));
+ const apolloRef = new ObservableQueryRef();
+ if (typeof options.variables === 'object') {
+ const varObs = observeVariables(options.variables);
+
+ return new ApolloQueryObservable(apolloRef, subscriber => {
+ const sub = varObs.switchMap(newVariables => {
+ const cleanOptions = omit(options, 'variables');
+ const newOptions = assign(cleanOptions, { variables: newVariables });
+
+ apolloRef.apollo = this.client.watchQuery(newOptions);
+
+ return apolloRef.apollo;
+ }).subscribe(subscriber);
+
+ return () => sub.unsubscribe();
+ });
+ }
+
+ apolloRef.apollo = this.client.watchQuery(options);
+ return new ApolloQueryObservable(apolloRef);
}
public query(options) {
diff --git a/src/apolloQueryObservable.ts b/src/apolloQueryObservable.ts
index c8301dd79..dddf0e64f 100644
--- a/src/apolloQueryObservable.ts
+++ b/src/apolloQueryObservable.ts
@@ -2,13 +2,12 @@ import { Observable } from 'rxjs/Observable';
import { Subscriber } from 'rxjs/Subscriber';
import { Subscription } from 'rxjs/Subscription';
import { Operator } from 'rxjs/Operator';
-import { $$observable } from 'rxjs/symbol/observable';
+import { ApolloQueryResult } from 'apollo-client';
-import { FetchMoreOptions } from 'apollo-client/ObservableQuery';
-import { FetchMoreQueryOptions } from 'apollo-client/watchQueryOptions';
+import { ObservableQueryRef, IObservableQuery } from './utils/observableQuery';
-export class ApolloQueryObservable extends Observable {
- constructor(public apollo: any, subscribe?: (subscriber: Subscriber) => Subscription | Function | void) {
+export class ApolloQueryObservable extends Observable implements IObservableQuery {
+ constructor(public apollo: ObservableQueryRef, subscribe?: (subscriber: Subscriber) => Subscription | Function | void) {
super(subscribe);
}
@@ -23,7 +22,7 @@ export class ApolloQueryObservable extends Observable {
// apollo-specific methods
- public refetch(variables?: any): Promise {
+ public refetch(variables?: any): Promise {
return this.apollo.refetch(variables);
}
@@ -35,14 +34,7 @@ export class ApolloQueryObservable extends Observable {
return this.apollo.startPolling(p);
}
- public fetchMore(options: FetchMoreQueryOptions & FetchMoreOptions): Promise {
+ public fetchMore(options: any): Promise {
return this.apollo.fetchMore(options);
}
-
- // where magic happens
-
- protected _subscribe(subscriber: Subscriber) {
- const apollo = this.apollo;
- return apollo[$$observable]().subscribe(subscriber);
- }
}
diff --git a/src/utils/observableQuery.ts b/src/utils/observableQuery.ts
new file mode 100644
index 000000000..d683ade0e
--- /dev/null
+++ b/src/utils/observableQuery.ts
@@ -0,0 +1,34 @@
+import {
+ ObservableQuery,
+} from 'apollo-client/ObservableQuery';
+
+import {
+ ApolloQueryResult,
+} from 'apollo-client';
+
+export interface IObservableQuery {
+ refetch: (variables?: any) => Promise;
+ fetchMore: (options: any) => Promise;
+ stopPolling: () => void;
+ startPolling: (p: number) => void;
+}
+
+export class ObservableQueryRef implements IObservableQuery {
+ public apollo: ObservableQuery;
+
+ public refetch(variables?: any): Promise {
+ return this.apollo.refetch(variables);
+ }
+
+ public stopPolling(): void {
+ return this.apollo.stopPolling();
+ }
+
+ public startPolling(p: number): void {
+ return this.apollo.startPolling(p);
+ }
+
+ public fetchMore(options: any): Promise {
+ return this.apollo.fetchMore(options);
+ }
+}
diff --git a/src/utils/observeVariables.ts b/src/utils/observeVariables.ts
new file mode 100644
index 000000000..6aa526122
--- /dev/null
+++ b/src/utils/observeVariables.ts
@@ -0,0 +1,41 @@
+import { Observable } from 'rxjs/Observable';
+import { Observer } from 'rxjs/Observer';
+
+import 'rxjs/add/observable/combineLatest';
+
+export function observeVariables(variables?: Object): Observable