by Gerard Sans (@gerardsans)
Spoken at 56 events in 18 countries
900
1.2K
Angular In Flip Flops
GraphQL created at Facebook
GraphQL is open sourced
Relay Classic is open sourced
New GraphQL website graphql.org
First GraphQL Summit
GitHub announces GraphQL API
Angular (v2)
Relay Modern 1.0
Apollo Client 2.0
Angular (v5)
npm install --global graphcool graphcool init
graphcool push graphcool console
// project.graphcool
type Todo @model {
id: ID! @isUnique
text: String!
complete: Boolean!
}
Apollo
Cache
Apollo
Link
const query = gql`query AllTodos {
allTodoes { id text complete }
}`;
const data = store.readQuery<Todos>({ query });
const newTodo = {
id: createTodo.id,
text: input.value,
complete: false,
__typename: "Todo"
};
store.writeQuery({
query,
data: {
allTodoes: [...data.allTodoes, newTodo],
},
});
export class GraphQLModule {
constructor(
private apollo: Apollo,
private httpLink: HttpLink
) {
const http = httpLink.create();
const authMiddleware = new ApolloLink((operation, forward) => {
operation.setContext({
headers: { 'Authorization': localStorage.getItem('token') || '' }
});
return forward(operation);
});
apollo.create({
link: concat(authMiddleware, http)
});
}
}
source: blog
@NgModule({
imports: [ HttpClientModule, HttpLinkModule ],
exports: [ ApolloModule ]
})
export class GraphQLModule {
constructor( apollo: Apollo, httpLink: HttpLink ) {
apollo.create({
// localhost/graphql (default)
link: httpLink.create({
uri: GRAPHCOOL_URI
}),
cache: new InMemoryCache(),
});
}
}
// app.module.ts
import { GraphQLModule } from './graphql.module';
@NgModule({
imports: [
BrowserModule,
GraphQLModule,
],
bootstrap: [AppComponent]
})
export class AppModule { }
schema {
query: Query,
mutation: Mutation
}
type Todo {
id: ID!
text: String!
complete: Boolean!
}
type Query {
allTodoes(skip: Int, take: Int): [Todo!]!
}
// app.component.ts
@Component()
export class App {
constructor(private apollo: Apollo){
let query = apollo.query({
query: gql`query todos {
allTodoes { id complete text } }`
});
let subscription = query.valueChanges.subscribe({
next: result => {
// result.loading
// result.data.allTodoes
},
error: error => {
console.log(`Error: ${error.message}`);
}
});
}
}
// todoList.component.ts
@Component({
template:
`<todo *ngFor="let todo of todos | async">{{todo.text}}</todo>`
})
class TodoList implements OnInit {
todos: Observable<any>;
constructor(private apollo: Apollo) { }
ngOnInit() {
const query = this.apollo.watchQuery({ query: todosQuery });
this.todos = query.valueChanges.map(({data}) => data.allTodoes);
}
// onRefresh = query.refetch;
}
// todo.component.ts
@Component()
export class Todo {
constructor(private apollo: Apollo) { }
private onTodoClick(){
let toggle$ = this.apollo.mutate({
mutation: gql`
mutation toggleTodo($id: ID!, $complete: Boolean!) {
updateTodo(id: $id, complete: $complete) { id text complete }
}`,
variables: { id: this.id, complete: !this.complete },
let subscription = toggle$.subscribe(
({ data }) => { // data.updateTodo.id }
);
}
}
source: blog
export class GraphQLModule {
constructor(
private apollo: Apollo,
private httpLink: HttpLink
) {
const link = this.setupLink();
const cache = new InMemoryCache();
apollo.create({ link, cache });
}
}
private setupLink() {
const http = this.httpLink.create({
uri: GRAPHCOOL_URI
});
const websocket = new WebSocketLink(
new SubscriptionClient(GRAPHCOOL_URI_WS, {
reconnect: true
})
);
const link = ApolloLink.split(
(op) => {
const ast = getOperationAST(op.query, op.operationName);
return ast && ast.operation === 'subscription';
},
/* if true use */ websocket,
/* if false use */ http
);
return link;
}
schema {
subscription: Subscription
}
type Mutation {
createTodo(text: String!, complete: Boolean!): Todo
deleteTodo(id: ID!): Todo
}
type Subscription {
Todo(filter: [CREATED, UPDATED, DELETED]): {
mutation: [CREATED, UPDATED, DELETED]
node: Todo
updatedFields: [String!]
previousValues: Todo
}
}
// app.component.ts
query.subscribeToMore({
document: gql`
subscription {
Todo(filter: { mutation_in: [CREATED] }) {
node {
id
complete
text
}
}
}
`,
updateQuery: (state: Todos, { subscriptionData }) => {
...
}
// app.component.ts
updateQuery: (state, { subscriptionData }) => {
const {node: node} = (subscriptionData as any).Todo;
if (!state.allTodoes.find(todo =>
todo.id === node.id)) {
state.allTodoes.push(node);
}
return {
allTodoes: todos
}
}
gsans/todo-apollo-v2