by Gerard Sans (@gerardsans)
Laptops shiny and ready by 14:45
Install github.com/gsans/iwd2017-first-graphql-app
14:45 Welcome
Instructions and setup
Slides
Practice, Q&A
16:30 Wrapping up
800
700
// index.html
<my-app ng-version="4.0.0-rc.2">
<div>
<h2>Hello Angular 4! 👋</h2>
</div>
</my-app>
GraphQL created at Facebook
Support Mobile Native Teams
GitHub announces GraphQL API
New GraphQL website
First GraphQL Summit
GraphQL First
GraphQL Europe
Apollo Client 0.10.0 (RC-0)
source: blog
// GET '/graphql'
{
user(name: "gsans") {
twitter
}
}
// result
{
"user": {
"twitter": "@gerardsans"
}
}
<app>
<add-todo>
<input><button>Add todo</button>
</add-todo>
<todo-list>
<ul>
<todo id="0" completed="false"><li>buy milk</li></todo>
</ul>
</todo-list>
<filters>
Show: <filter-link><a>All</a><filter-link> ...
</filters>
</app>
schema {
query: Query,
mutation: Mutation
}
type Query {
allTodoes(skip: Int, take: Int): [Todo!]!
}
type Todo {
id: ID!
text: String!
complete: Boolean!
}
schema {
query: Query,
mutation: Mutation,
}
type Mutation {
createTodo(text: String!, complete: Boolean!): Todo
updateTodo(id: ID!, text: String, complete: Boolean): Todo
}
source: blog
// client.ts
import { ApolloClient, createNetworkInterface } from 'apollo-client';
const client = new ApolloClient({
networkInterface: createNetworkInterface({
uri: 'https://api.graph.cool/ZZZ'
})
});
export function provideClient(): ApolloClient {
return client;
}
// app.module.ts
import { provideClient } from 'apollo-client';
import { ApolloModule } from 'angular2-apollo';
import { App } from './app.component';
@NgModule({
imports: [
BrowserModule,
ApolloModule.withClient(provideClient)
],
declarations: [ App ],
bootstrap: [ App ]
})
class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
// app.component.ts
@Component({ ... })
export class App {
constructor(private apollo: Angular2Apollo){
let query$ = apollo.query({
query: gql`query todos {
allTodoes { id complete text } }`,
forceFetch: true
});
let subscription = query$.subscribe({
next: result => {
// result.data.allTodoes
},
error: error => {
console.log(`Error: ${error.message}`);
}
});
}
}
// todo.component.ts
@Component({ ... })
export class Todo {
private onTodoClick(){
let toggle$ = this.apollo.mutate({
mutation: gql`
mutation toggleTodo($id: ID!, $complete: Boolean!) {
updateTodo(id: $id, complete: $complete) { id complete }
}`,
variables: { id: this.id, complete: !this.complete }
});
let subscription = toggle$.subscribe(
({ data }) => { // data.updateTodo.id }
);
}
}
// todoList.component.ts
@Component({
template:
`<todo *ngFor="let todo of todos | async">{{todo.text}}</todo>`
})
class TodoList implements OnInit {
todos: ApolloQueryObservable<any>;
constructor(private apollo: Angular2Apollo) { }
ngOnInit() {
this.todos = this.apollo.watchQuery({ query: todosQuery })
.map(({data}) => data.allTodoes);
}
// onRefresh = this.data.refetch;
}
(Experimental)
source: blog
// client.ts
import { Client } from 'subscriptions-transport-ws';
export const wsClient = new Client('ws://subscriptions.graph.cool/ZZZ', {
timeout: 10000
});
schema {
query: Query,
mutation: Mutation,
subscription: Subscription
}
type Post {
id: ID!
description: String!
imageUrl: String!
}
type Mutation {
createPost(description: String!, imageUrl: String!): Post
}
type Subscription {
createPost(): Post
}
// feed.component.ts
wsClient.subscribe({
query: `subscription newPosts {
createPost { id description imageUrl }
}`,
variables: null
}, (err, res) => {
// res.createPost = { id: 34, description: 'woot', imageUrl: '...' }
// err = [{ message: 'Connection Timeout', stack: '...' }]
});