Angular 2 meets GraphQL and

Apollo Client

slides.com/gerardsans | @gerardsans

Google Developer Expert

Master of Ceremonies

International Speaker

Angular 2 Trainer

Community Leader

800

500

Angular 2

Yay! Released!

Ready for Production

  • Declarative Templating
  • Change Detection
  • Dependency Injection
  • Component Model
  • Ahead-of-Time Compilation
  • Web, Mobile and Desktop

Community Adoption

GraphQL

GraphQL

  • Developed at Facebook 2012
  • Support Mobile Native Teams 
  • Open sourced in 2015
  • Framework agnostic

GraphQL Server

source: blog

Query Language


// Query
{
 user(name: "gsans") {
  twitter
 }
}

// Result
{
 "user": {
  "twitter": "@gerardsans"
 }
}

GraphQL Server

source: blog

Who is using it?

GraphQL Schema

Type System

  • Scalar Types: Int, Float, String, Boolean, ID 
  • Object Types: Todo
  • Entry points: Query, Mutation

Syntax

  • Nullable: String, Todo
  • Non-nullable: String!, Todo!
  • Arrays: [String], [Todo]

Todos Schema (1/2)

schema { 
  query: Query,  
  mutation: Mutation 
}

type Query {
  allTodoes(skip: Int, take: Int): [Todo!]!
}

type Todo {  
  id: ID!
  text: String!
  complete: Boolean!
}

Todos Schema (2/2)

schema { 
  query: Query,  
  mutation: Mutation 
}

type Mutation {
  createTodo(text: String!, complete: Boolean!): Todo
  updateTodo(id: ID!, text: String, complete: Boolean): Todo
}

GraphiQL

Solution Architecture

Components Tree

<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>

demo

State Management

Dan Abramov

@gaearon

Redux

Main Features

  • Unidirectional data flow
  • Single Immutable State
  • New states are created without side-effects

Unidirectional data flow

Apollo Client

Overview

Setup

// client.ts
import ApolloClient, { createNetworkInterface } from 'apollo-client';

export const client = new ApolloClient({
  networkInterface: createNetworkInterface('https://api.graph.cool/ZZZ'),
});

Bootstrap

// app.module.ts
import { client } from 'apollo-client';
import { ApolloModule } from 'angular2-apollo';
import { App } from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    ApolloModule.withClient(client)
  ],
  declarations: [ App ],
  bootstrap: [ App ]
})
class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);

Main APIs

  • query (Promise)
  • watchQuery (Observable)
  • mutate (Promise)
  • updateQueries (reducer)

query (Promise)

// app.component.ts
@Component({ ... })
export class App { 
   constructor(private apollo: Angular2Apollo){
    apollo.query({
      query: gql`query todos { 
        allTodoes { id complete text } }`, 
      forceFetch: true
    }).then(result => {
      // result.data.allTodoes
    }).catch(error => {
      console.log(`Error: ${error.message}`);
    });
  }
}

mutate (Promise)

// todo.component.ts
@Component({ ... })
export class Todo {
 private onTodoClick(){ 
  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 }
  }).then(({ data }) => { // data.updateTodo.id }); 
 }
}

watchQuery (Observable)

// todoList.component.ts
@Component({
  template:
    `<todo *ngFor="let todo of todos | async">{{todo.text}}</todo>`
})
class TodoList implements OnInit {
  data: ApolloQueryObservable<any>;
  constructor(private apollo: Angular2Apollo) { }

  ngOnInit() {
    this.data = this.apollo.watchQuery({ query: todosQuery })
      .map(({data}) => data.allTodoes);
  }
  // onRefresh = this.data.refetch;
}

Why use GraphQL?

Some reasons

  • Super fast
  • De-coupled from storage
  • Declarative
  • Validated and structured
  • Facilitates Collaboration

Thanks!