How to use Apollo Server 2 and GraphQL

How to use Apollo Server 2 and GraphQL

Learn GraphQL, Apollo Server 2, and Black-box Testing. In this tutorial I will be showing you how to use Apollo Server 2 and GraphQL. Understanding of GraphQL by setting up your GraphQL schema that represents the structure of your data set, furthermore, we will do this by looking at TypeDefs (type definitions). We will be using Jest to test our data sources, and then we will be creating black-box tests (snapshots) to test our typedefs & resolvers -- which will be hooked up to fixture files (mock data).

In this video I will be showing you how to use Apollo Server 2 and GraphQL. You will gain an understanding of GraphQL by setting up your GraphQL schema that represents the structure of your data set, furthermore, we will do this by looking at TypeDefs (type definitions). Once we have created our schema the next step will be to let Apollo Server know how to interact with that schema, essentially how to execute queries. To do this we will use something called a resolver, a resolver essentially tells Apollo how to fetch data, moreover how to fetch data for a particular type. Once we have setup our resolvers we will look at data sources. Data sources are nothing more than a class that sets out our scaffolding for making requests to external APIs (in our case). Although we just touch the surface of what a data source can do by using RESTDataSource, they can do much more.

Towards the end of this video, we will be using Jest to test our data sources, and then we will be creating black-box tests (snapshots) to test our typedefs & resolvers -- which will be hooked up to fixture files (mock data). For a quick TLDR of what we have done, skip to 2:58:49 - I essentially went with the format of 'schema (typedefs) -- resolvers -- datasources'.

⏳ Timeline
0:00:00 - Reviewing where we left off
0:03:19 - Quick look over the UI of the first tutorial
0:03:30 - Github repo of the first project
0:04:06 - Reviewing the read me
0:04:21 - Initial setup for our application
0:04:36 - Creating our package.json file
0:07:01 - Optional chaining import!
0:09:46 - Installing all our packages
0:10:26 - Creating our server.js file
0:11:11 - Setting up ApolloServer
0:12:41 - Setting up our typedefs
0:12:51 - Setting up our resolvers
0:13:30 - Quick talk about how GraphQL handles field requests
0:15:47 - Similarities between GQL & RPC
0:18:07 - Adding typedefs within (typedefs/index.js)
0:19:02 - Creating our Article object type
0:20:22 - Defining an instance of an executable query
0:21:32 - Adding more fields to our Article object type
0:26:25 - Creating our essential .babelrc file
0:26:55 - Starting our server!
0:27:25 - Exploring Graphiql on port 4000
0:33:55 - Executing a dummy query
0:36:10 - Hooking up our resolvers
0:37:49 - Exploring resolver arguments
0:39:54 - Logging our executable query arguments
0:40:19 - Exploring the context argument
0:44:09 - Creating our datasource files
0:49:01 - Implementing the hackernews.js datasource
0:52:30 - Explaining RESTDataSource
1:00:01 - Adding methods to our datasource
1:03:36 - Adding a transformer method
1:05:06 - Adding our datasource to our index.js
1:06:01 - Accessing our datasource via the context argument
1:07:21 - Adding all datasources to the context
1:09:51 - Our first successful query via Graphiql!
1:10:56 - Adding more resolvers
1:13:22 - Adding more executable queries into our typedefs
1:15:12 - Debugging syntax errors
1:18:08 - Succesful query responses
1:23:08 - Async resolver explained
1:27:23 - Testing our allArticles resolver
1:31:23 - Adding the New York Times datasource
1:40:03 - Adding the fixture files for testing
1:43:23 - Testing the HackerNews datasource
2:02:03 - Looking at the Apollo documentation for testing
2:06:13 - Testing the HackerNews queries
2:28:48 - Running our black-box tests
2:40:32 - The difference in mocking return objects/arrays
2:43:38 - Checking our coverage levels
2:45:05 - Testing the New York Times datasource
2:49:00 - Testing the New York Times queries
2:52:25 - Checking coverage, nearly at 100%
2:55:15 - 100% test coverage (unit & black-box tests)
2:55:50 - Quick look at aliases
2:58:49 - TLDR: overview of the project!
3:08:00 - Signing off!

Explore GraphQL with Apollo & React: Build a Superhero Database

Explore GraphQL with Apollo & React: Build a Superhero Database

In this article, We share some light on what GraphQL is and give you an opportunity for some hands-on experience with Apollo and React.

In this article, We share some light on what GraphQL is and give you an opportunity for some hands-on experience with Apollo and React.

Curious about all the buzz surrounding GraphQL, but not quite sure why you should be excited? You’re in the right place! We’ll shed some light on what GraphQL is and give you an opportunity for some hands-on experience.

Let’s start by clearing the air and answering the $20,000 question: what is GraphQL? No, it’s not an obscure function on your TI-89. It’s a query language at heart — or query specification more accurately — that can be used to fetch data from just about any data source.

Better yet, it allows you to fetch the exact data you need — no more, no less — in a single network request. While that may not sound like the sexiest tech to come out of the Facebook factory of innovation, you may just find yourself pleasantly surprised at how useful it can be.

All that’s needed is an Apollo server to act as our endpoint and a React app using the Apollo client to leverage any data within. We’ll tackle the server first.

Getting Started with Apollo Server

To get our Apollo server started, create a folder called apollo-server in your favorite working directory. Next, enter that directory and run the following npm command — you do have npm and Node installed, right? — to get the Apollo framework in place:

npm install apollo-server apollo-server-express graphql

Now that you’ve got the various bits and pieces of the Apollo server in place, it’s time to actually tell our server what to serve. Go ahead and create an empty index.js file in the apollo-server directory and add the following to it:

const { ApolloServer, gql } = require('apollo-server');

This line simply pulls in the required objects for starting an Apollo server and parsing our query strings into query documents for GraphQL.

Our First GraphQL Schema

Next up, let’s add our first schema:

// This will be our GraphQL schema
const typeDefs = gql`
  type User {
    id: ID!
    name: String
    superpowers: [Superpower]!
  }

  type Superpower {
    id: ID!
    text: String
  }

  type Query {
    users: [User]
    user(id: ID!): User
  }
`;

Here we add our type definitions. The first is of type User which we define as an object having an id, name, and superpowers field. The second is a simple id and text to describe each superpower. Finally, the third defines two acceptable queries — users and user — that, respectively, return all users or a single user that matches the provided id argument.

Pretty easy, right?

Adding a Dash of Data

Next, let’s add some mock data to bring our schema to life:

// This will be our mock data to query
const users = [{
  id: '1',
  name: 'Peter Parker',
  superpowers: [{
    id: '1',
    text: 'Web slinging'
  },{
    id: '2',
    text: 'Spidey sense'
  }]
},{
  id: '2',
  name: 'Tony Stark',
  superpowers: [{
    id: '3',
    text: 'Industrial design'
  },{
    id: '4',
    text: 'Robotic fashion'
  }]
}];

All we’re doing here is adding two users to our mock data. It’s worth pointing out that GraphQL isn’t relegated to only querying JavaScript arrays. This could be any database or other data construct. We’re just keeping things simple here to focus on the task at hand.

Don’t Forget Resolvers

Next up, we need to tell GraphQL how to interpret the queries we defined above. This is done with resolvers:

// This will be a map of functions to return the data described by our schema
const resolvers = {
  Query: {
    users: () => {
      return users
    },
    user: (root, { id }) => {
      return users.find(user => user.id === id);
    },
  },
};

You’ll notice the first query users requires no arguments and returns the entire users list (at least in theory, more on that later). The second query user accepts the ID of the user to be fetched and returns said user.

Putting It All Together

To finish off our Apollo server, we just need to instantiate a new instance and start listening for connections:

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`Apollo server started at ${url}`)
});

Here we send the ApolloServer constructor our schema and resolvers created above. All that’s needed then is to actually start the server, but first, here’s what your index.js should look like:

const { ApolloServer, gql } = require('apollo-server');

// This will be our GraphQL schema
const typeDefs = gql`
  type User {
    id: ID!
    name: String
    superpowers: [Superpower]!
  }

  type Superpower {
    id: ID!
    text: String
  }

  type Query {
    users: [User]
    user(id: ID!): User
  }
`;

// This will be our mock data to query
const users = [{
  id: '1',
  name: 'Peter Parker',
  superpowers: [{
    id: '1',
    text: 'Web slinging'
  },{
    id: '2',
    text: 'Spidey sense'
  }]
},{
  id: '2',
  name: 'Tony Stark',
  superpowers: [{
    id: '3',
    text: 'Industrial design'
  },{
    id: '4',
    text: 'Robotic fashion'
  }]
}];

// This will be a map of functions to return the data described by our schema
const resolvers = {
  Query: {
    users: () => {
      return users
    },
    user: (root, { id }) => {
      return users.find(user => user.id === id);
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`Apollo server started at ${url}`)
});

Go ahead and fire it up with node index.js and visit http://localhost:4000/ to see the fruit of your labor!

You should be greeted with a GraphQL playground that lets you try out interactive queries against the schema you’ve created.

Going Hands-on

Let’s test it out by entering this query in the left-hand pane:

query {
  user(id: 1) {
    name
  }
}

Here we use the user query we just set up, and pass it the id of 1. We’re also telling GraphQL that we only want to return the name of said user. The result in the left hand pane — after clicking the play-like button — should look like this:

{
  "data": {
    "user": {
      "name": "Peter Parker"
    }
  }
}

Let’s say you want to take a peek at his superpowers too. All you have to do is request that field:

query {
  user(id: 1) {
    name,
    superpowers {
      text
    }
  }
}

We added the superpowers field and, since we only care about the text and not the superpower ID, we specify as much. The result should now display each superpower for our first user:

{
  "data": {
    "user": {
      "name": "Peter Parker",
      "superpowers": [
        {
          "text": "Web slinging"
        },
        {
          "text": "Spidey sense"
        }
      ]
    }
  }
}

Say we want to grab all users and their superpowers, we can rely on the users query we defined:

query {
  users {
    id,
    name,
    superpowers {
      text
    }
  }
}

And the result:

{
  "data": {
    "users": [
      {
        "id": "1",
        "name": "Peter Parker",
        "superpowers": [
          {
            "text": "Web slinging"
          },
          {
            "text": "Spidey sense"
          }
        ]
      },
      {
        "id": "2",
        "name": "Tony Stark",
        "superpowers": [
          {
            "text": "Industrial design"
          },
          {
            "text": "Robotic fashion"
          }
        ]
      }
    ]
  }
}

Only care about superpowers? We can do that too:

query {
  users {
    superpowers {
      text
    }
  }
}

And you get:

{
  "data": {
    "users": [
      {
        "superpowers": [
          {
            "text": "Web slinging"
          },
          {
            "text": "Spidey sense"
          }
        ]
      },
      {
        "superpowers": [
          {
            "text": "Industrial design"
          },
          {
            "text": "Robotic fashion"
          }
        ]
      }
    ]
  }
}

At this point you should be able to appreciate the supreme flexibility and allure of GraphQL. With a single query and connection we can retrieve any slice of the data we desire. All that’s necessary is a well designed schema and the resolvers to support it.

Even better, back-end developers and front-end developers can do their thing almost independently. With the schema acting as a middle man, both groups can effectively avoid stepping on each other’s toes. And really, that’s GraphQL in a nutshell. Before we wrap this tutorial up however, let’s take a look at how to integrate these queries with an actual React app.

Introducing React to the Mix

Go back to your root working directory and run the following commands to set up a bootstrapped React app with the requisite GraphQL and Apollo libraries:

npm install -g create-react-app
create-react-app my-graphql
cd my-graphql
npm install apollo-boost react-apollo graphql

Next, replace the contents of src/index.js with the following:

index.js:

import React from 'react'
import ReactDOM from 'react-dom'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloProvider } from 'react-apollo'

import App from './App'

const client = new ApolloClient({
    link: new HttpLink({ uri: 'http://localhost:4000/graphql' }),
    cache: new InMemoryCache()
})

ReactDOM.render(
    <ApolloProvider client={client}>
    <App />
    </ApolloProvider>,
    document.getElementById('root')
)

All we need here are the usual imports for a React app along with the Apollo client to interface with our new Apollo server. To create the Apollo client we just need a link to the server http://localhost:4000/graphql and a way to cache our goods. With that, we simply render the app.

Next, we need to set up the app to query and display the data presented by our Apollo server. Go ahead and replace the default src/App.js with this:

App.js:

import React from 'react'
import { Query } from 'react-apollo'
import { gql } from 'apollo-boost'

const TEST_QUERY = gql`
  {
    user(id: 1) {
      id,
      name,
      superpowers {
        text
      }

  }}
`;

const App = () => (
  <Query query={TEST_QUERY}>
  {({ data: { user }, loading }) => {
      if (loading || !user) {
        return <div>Loading ...</div>;
      }
      return (
    <p>
        {user.name} ({user.id}) has the following superpowers:
        <ul>
        {user.superpowers.map(superpower => (
            <li>
                {superpower.text}
            </li>
        ))}
        </ul>
    </p>
      );
    }}
  </Query>
);

export default App

You should see some familiar patterns here. We first use gql to create a GraphQL query document that requests the user with ID 1 — more specifically, their ID, name and superpowers text. Then we pass the document to our server with the Query tag. It’s here that we can format the results in a pretty React app.

Go ahead and start the server with npm start and check out the beautiful results at http://localhost:3000/.

And with that, our tutorial is complete. You’ve created an Apollo server and fed it some simple data structures. You discovered how to write schemas and resolvers to define interactions with the data. You then practiced querying specific pieces of that data. Finally, you tied it all together with a React app that retrieves data from the server and presents it in a nicely formatted way.

While this should be enough to get you started with integrating GraphQL in your future projects, there’s lots still to learn. Mutations for adding and changing data is a great next step.

How to build a Blog App with GraphQL, Apollo client and Vuejs

How to build a Blog App with GraphQL, Apollo client and Vuejs

In this tutorial, we'll be showing how to build a blog app with GraphQL, Apollo client and VueJS

In this tutorial, I'll be showing how to build a blog that will make use of the GraphQL server built in that tutorial. We'll build the blog app using Apollo client and VueJS.

Table of Contents

  • Enabling CORS
  • Starting the GraphQL Server
  • Create a Vue App
  • Installing Necessary Packages
  • Setting Up Vue Apollo
  • Adding Bulma
  • Removing Unused Code
  • Adding Master Layout
  • User Signup
  • Adding Signup Route
  • User Login
  • Adding Login Route
  • Creating Menu Component
  • Displaying Users
  • Adding Users Route
  • Viewing User Details
  • Adding User Details Route
  • Authorizing User
  • Adding New Post
  • Adding Add Post Route
  • Displaying Posts
  • Adding Posts Route
  • Creating Blog Homepage
  • Adding Home Route
  • Viewing A Post
  • Adding View Post Route
  • Conclusion
Enabling CORS

The GraphQL server was built with AdonisJS. AdonisJS makes dealing with Cross-Origin Resource Sharing(CORS) a breeze, as it provide a package which we can use to handle CORS on our API. By default CORS is turned off on AdonisJS, so we need to enable it. To enable CORS on AdonisJS app, we simply set origin to true in config/cors.js as below:

// config/cors.js

// allow current request origin
origin: true

Though the cloned GraphQL server has CORS already enabled, but it's worth mentioning it.

Starting the GraphQL Server

Since our blog app will be making use of the GraphQL server, we'll need to start the server and keep it running for the rest of the tutorial. To do start, we'll cd into the GraphQL server project (the one cloned from above) directory and run the command below:

adonis serve --dev

This will start the GraphQL server and keep it running.

The rest of the tutorial assumes you already started the GraphQL server and it is running.

With that taken care of, let's start building our blog app.

Create a Vue App

We'll start by creating a new Vue app using the Vue CLI:

vue init webpack graphql-blog-app
// select `Y` to use Vue router

This will create a new Vue app with the name graphql-blog-app and install it dependencies.

Installing Necessary Packages

With the app created, we can move on to installing the necessary packages for building our GraphQL blog app:

cd graphql-blog-app
npm install --save [email protected] graphql apollo-client apollo-link apollo-link-context apollo-link-http apollo-cache-inmemory graphql-tag

Let's quickly go over each package:

  • vue-apollo: An Apollo/GraphQL integration for VueJS. We install the latest version of the plugin which allows us to use all the great features that comes with Apollo client 2.0.
  • graphql: A reference implementation of GraphQL for JavaScript.
  • apollo-client: A fully-featured, production ready caching GraphQL client for every server or UI framework.
  • apollo-link: A standard interface for modifying control flow of GraphQL requests and fetching GraphQL results.
  • apollo-link-context: Used to easily set a context on your operation, which is used by other links further down the chain.
  • apollo-link-http: Used to get GraphQL results over a network using HTTP fetch.
  • apollo-cache-inmemory: Cache implementation for Apollo Client 2.0.
  • graphql-tag: A JavaScript template literal tag that parses GraphQL queries.
Setting Up Vue Apollo

Next, let's put the packages to use. We'll start by creating an ApolloClient instance and install the VueApollo plugin. Open src/main.js and add the code below to it:

// src/main.js

import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'

const httpLink = new HttpLink({
    // URL to graphql server, you should use an absolute URL here
    uri: 'http://localhost:3333/graphql'
})

// create the apollo client
const apolloClient = new ApolloClient({
    link: httpLink,
    cache: new InMemoryCache()
})

// install the vue plugin
Vue.use(VueApollo)

We create a new instance of httpLink with the URL (mine is http://localhost:3333/graphql) of our GraphQL server. Then we create an Apollo client using the httpLink created above and specify we want an in memory cache. Lastly, we install the Vue Apollo plugin.

Next, let's create a apolloProvider object which we'll specify on our root component:

// src/main.js

const apolloProvider = new VueApollo({
  defaultClient: apolloClient
})

// update Vue instance by adding `apolloProvider`
new Vue({
    el: '#app',
    router,
    apolloProvider,
    template: '<App/>',
    components: { App }
})

We create a new instance of the Vue Apollo plugin using the apolloClient created as our default client. Lastly, we make use of the apolloProvider object by adding it in our Vue instance, same way we would use Vue router.

Adding Bulma

For the purpose of this tutorial, we'll be using Bulma CSS. So, let's add it in. Open index.html and update as below:

// index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>GraphQL Blog App</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
</head>
<body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
</body>
</html>

We reference Bulma on CDN.

Removing Unused Code

There are some files and code that came along when we created our Vue app which we won't be using in this tutorial. Let's remove them so they won't interfere with our app. Delete the Hello component and remove all it references from src/router/index.js.

Adding Master Layout

The blog will use a generic layout across it pages. In that case, let's define a layout that all pages will use. To do this, open src/App.vue and update as below:

// src/App.vue

<template>
    <div id="app">
        <nav class="navbar is-primary" role="navigation" aria-label="main navigation">
            <div class="container">
                <div class="navbar-brand">
                    <router-link class="navbar-item" to="/">Blog App</router-link>

                    <button class="button navbar-burger">
                        <span></span>
                        <span></span>
                        <span></span>
                    </button>
                </div>
            </div>
        </nav>
        <router-view/>
    </div>
</template>

<script>
export default {
    name: 'app'
}
</script>

We add a header that all pages will use.

User Signup

Users should be able to signup to our blog app. We'll create a SignUp component that will handle that. So, within src/components create a new Admin folder. All admin related components will be created insider this folder.

Before we create the SignUp component, let's create a dedicated file that will hold all our GraphQL queries and mutations. We'll create this file directly inside src. Create a graphql.js file inside src and paste the code below into it:

// src/graphql.js

import gql from 'graphql-tag'

export const SIGNUP_MUTATION = gql`mutation SignupMutation($username: String!, $email: String!, $password: String!) {
        createUser(
            username: $username,
            email: $email,
            password: $password
        ) {
            id
            username
            email
        }
    }`

This is the GraphQL mutation that will handle creating new user on our GraphQL server. It takes the username, email and password of a user. These variables will be passed from the SignUp component.

Next, let's create the SignUp component. Within the Admin folder, create a SignUp.vue file and paste the code below into it:

// src/components/Admin/SignUp.vue

<template>
    <section class="section">
        <div class="columns">
            <div class="column is-4 is-offset-4">
                <h2 class="title has-text-centered">Signup</h2>

                <form method="POST" @submit.prevent="signup">
                    <div class="field">
                        <label class="label">Username</label>

                        <p class="control">
                            <input
                                type="text"
                                class="input"
                                v-model="username">
                        </p>
                    </div>

                    <div class="field">
                        <label class="label">E-Mail Address</label>

                        <p class="control">
                            <input
                                type="email"
                                class="input"
                                v-model="email">
                        </p>
                    </div>

                    <div class="field">
                        <label class="label">Password</label>

                        <p class="control">
                            <input
                                type="password"
                                class="input"
                                v-model="password">
                        </p>
                    </div>

                    <p class="control">
                        <button class="button is-primary is-fullwidth is-uppercase">SignUp</button>
                    </p>
                </form>
            </div>
        </div>
    </section>
</template>

<script>
import { SIGNUP_MUTATION } from '@/graphql'

export default {
    name: 'SignUp',
    data () {
        return {
            username: '',
            email: '',
            password: ''
        }
    },
    methods: {
        signup () {
            this.$apollo
                .mutate({
                    mutation: SIGNUP_MUTATION,
                    variables: {
                        username: this.username,
                        email: this.email,
                        password: this.password
                    }
                })
                .then(response => {
                    // redirect to login page
                    this.$router.replace('/login')
                })
            }
        }
    }
</script>

This component renders a simple form for users to signup. Once the form is submitted, a signup method is called. Within the signup method, we make use of mutate method avaiable on this.$apollo (from the Vue Apollo plugin). We use the SIGNUP_MUTATION mutation created earlier and pass along the necessary variables. Once the signup process is successful (that is, the user has been created), we redirect the user to login page (which we'll create shortly).

Adding Signup Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import SignUp from '@/components/Admin/SignUp'

// add these inside the `routes` array
{
    path: '/signup',
    name: 'SignUp',
    component: SignUp
},

Now when we visit the /signup route, we should see our signup form as in the image below:

User Login

Let's add ability for users to login. Just as we did with user signup, let's first create the GraphQL mutation. Add the code below to src/graphql.js:

// src/graphql.js

export const LOGIN_MUTATION = gql`mutation LoginMutation($email: String!, $password: String!) {
        login(
            email: $email,
            password: $password
        )
    }`

This is the GraphQL mutation handles user login to our GraphQL server. It takes the email and password of a user.

Next, within the Admin folder, create a LogIn.vue file and paste the code below into it:

// src/components/Admin/LogIn.vue

<template>
    <section class="section">
        <div class="columns">
            <div class="column is-4 is-offset-4">
                <h2 class="title has-text-centered">Login</h2>

                <form method="POST" @submit.prevent="login">
                    <div class="field">
                        <label class="label">E-Mail Address</label>

                        <p class="control">
                            <input
                                type="email"
                                class="input"
                                v-model="email">
                        </p>
                    </div>

                    <div class="field">
                        <label class="label">Password</label>

                        <p class="control">
                            <input
                                type="password"
                                class="input"
                                v-model="password">
                        </p>
                    </div>

                    <p class="control">
                        <button class="button is-primary is-fullwidth is-uppercase">Login</button>
                    </p>
                </form>
            </div>
        </div>
    </section>
</template>

<script>
import { LOGIN_MUTATION } from '@/graphql'

export default {
    name: 'LogIn',
    data () {
        return {
            email: '',
            password: ''
        }
    },
    methods: {
        login () {
            this.$apollo
                .mutate({
                    mutation: LOGIN_MUTATION,
                    variables: {
                        email: this.email,
                        password: this.password
                    }
                })
                .then(response => {
                    // save user token to localstorage
                    localStorage.setItem('blog-app-token', response.data.login)

                    // redirect user
                    this.$router.replace('/admin/posts')
                })
        }
    }
}
</script>

This component renders a simple form for users to login. Once the form is submitted, a login method is called. Within the login method, we make use of mutate method. We use the LOGIN_MUTATION mutation created earlier and pass along the necessary variables. Once the login process is successful, we save the token gotten from our GraphQL server to localstorage and redirect the user.

Adding Login Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import LogIn from '@/components/Admin/LogIn'

// add these inside the `routes` array
{
    path: '/login',
    name: 'LogIn',
    component: LogIn
},

Now when we visit the /login route, we should see our login form as in the image below:

Creating Menu Component

Before we start fleshing out the admin-ish part of our blog, let's create a Menu component which will server as the sidebar navigational menu. Within the Admin folder, create a Menu.vue file and paste the code below into it:

// src/components/Admin/Menu.vue

<template>
    <aside class="menu">
        <p class="menu-label">Post</p>
        <ul class="menu-list">
            <li>
            <router-link to="/admin/posts/new">New Post</router-link>
            </li>
            <li>
            <router-link to="/admin/posts">Posts</router-link>
            </li>
        </ul>
        <p class="menu-label">User</p>
        <ul class="menu-list">
            <li>
                <router-link to="/admin/users">Users</router-link>
            </li>
        </ul>
    </aside>
</template>

This simply renders links to some admin sections of out blog app.

Displaying Users

On the admin section, we want to be able to see list users that has been created. For that, we'll created a Users component. But first, let's write the GraphQL query that will fetch all users created. Add the code below to src/graphql.js:

// src/graphql.js

export const ALL_USERS_QUERY = gql`query AllUsersQuery {
        allUsers {
            id
            username
            email
        }
    }`

This GraphQL query fetches all users from our GraphQL server.

Next, let's create the Users component. Within the Admin folder, create a Users.vue file and paste the code below into it:

// src/components/Admin/Users.vue

<template>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-3">
                    <Menu/>
                </div>
                <div class="column is-9">
                    <h2 class="title">Users</h2>

                    <table class="table is-striped is-narrow is-hoverable is-fullwidth">
                        <thead>
                            <tr>
                                <th>Username</th>
                                <th>Email</th>
                                <th></th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr
                                v-for="user in allUsers"
                                :key="user.id">
                                    <td>{{ user.username }}</td>
                                    <td>{{ user.email }}</td>
                                    <td>
                                        <router-link :to="`/admin/users/${user.id}`">View</router-link>
                                    </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </section>
</template>

<script>
import Menu from '@/components/Admin/Menu'
import { ALL_USERS_QUERY } from '@/graphql'

export default {
    name: 'Users',
    components: {
        Menu
    },
    data () {
        return {
            allUsers: []
        }
    },
    apollo: {
        // fetch all users
        allUsers: {
            query: ALL_USERS_QUERY
        }
    }
}
</script>

We make use of the Menu component created earlier. Then we define our data which will be populated once the data is gotten from our GraphQL server. Within the apollo object, we add our GraphQL query to fetch all users. This makes use of the ALL_USERS_QUERY we created above. It is important to note that, the name of our data (allUsers in this case) must be the same name used in our GraphQL query (allUsers in this case). Once allUsers is populated with data from our GraphQL server, we display the users in a table by looping through the array of users. We also add a link to view each user details.

Adding Users Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import Users from '@/components/Admin/Users'

// add these inside the `routes` array
{
    path: '/admin/users',
    name: 'Users',
    component: Users
},

Now when we visit the /admin/users route, we should see a list of users as in the image below:

Viewing User Details

In the last section, we add a link to view user details. Now, let's implement it. Add the code below to src/graphql.js:

// src/graphql.js

export const USER_QUERY = gql`query UserQuery($id: Int!) {
        user(id: $id) {
            id
            username
            email
            posts {
                id
            }
        }
    }`

This GraphQL query fetches a user by it ID from our GraphQL server. It takes the ID of the user as an argument. The user ID will be passed from the UserDetails component.

Next, let's create the UserDetails component. Within the Admin folder, create a UserDetails.vue file and paste the code below into it:

// src/components/Admin/UserDetails.vue

<template>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-3">
                    <Menu/>
                </div>
                <div class="column is-9">
                    <h2 class="title">User Details</h2>

                    <div class="field is-horizontal">
                        <div class="field-label is-normal">
                            <label class="label">Username</label>
                        </div>
                        <div class="field-body">
                            <div class="field">
                                <p class="control">
                                    <input class="input is-static" :value="user.username" readonly>
                                </p>
                            </div>
                        </div>
                    </div>

                    <div class="field is-horizontal">
                        <div class="field-label is-normal">
                            <label class="label">Email Address</label>
                        </div>
                        <div class="field-body">
                            <div class="field">
                                <p class="control">
                                    <input class="input is-static" :value="user.email" readonly>
                                </p>
                            </div>
                        </div>
                    </div>

                    <div class="field is-horizontal">
                        <div class="field-label is-normal">
                            <label class="label">Number of posts</label>
                        </div>
                        <div class="field-body">
                            <div class="field">
                                <p class="control">
                                    <input class="input is-static" :value="user.posts.length" readonly>
                                </p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
</template>

<script>
import Menu from '@/components/Admin/Menu'
import { USER_QUERY } from '@/graphql'

export default {
    name: 'UserDetails',
    components: {
        Menu
    },
    data () {
        return {
            user: '',
            id: this.$route.params.id
        }
    },
    apollo: {
        // fetch user by ID
        user: {
            query: USER_QUERY,
            variables () {
                return {
                    id: this.id
                }
            }
        }
    }
}
</script>

We display the specified user's username, email and number of posts created. The USER_QUERY accept the ID of the user we want to view his/her details. The user ID is gotten from the route params. That is, given /admin/users/12, 12 is the ID of a particular user. We need a way to pass this ID to our query. To do this, we make use of reactive parameter by defining a variables function that returns an object containing the user ID.

Adding User Details Route

Open src/router/index.js, and add the code below to it. This route should be below all the previous routes:

// src/router/index.js

import UserDetails from '@/components/Admin/UserDetails'

// add these inside the `routes` array
{
    path: '/admin/users/:id',
    name: 'UserDetails',
    component: UserDetails,
    props: true
},

We should be able to view a particular user detail now:

Authorizing User

Only authenticated users can add new post. So, we need a way to pass an Authorization header with the user token along with the request to add new post which will signify the user can actually add new post. With apollo-link-context, we can easily do this. Open src/main.js and add the code below to it:

// src/main.js

import { setContext } from 'apollo-link-context'

const authLink = setContext((_, { headers }) => {
    // get the authentication token from localstorage if it exists
    const token = localStorage.getItem('blog-app-token')

    // return the headers to the context so httpLink can read them
    return {
        headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : null
        }
    }
})

// update apollo client as below
const apolloClient = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache()
})

First, we import apollo-link-context. Then we make use of it to create an authLink that gets the user token from local storage and return the headers which contains the Authorization header. Lastly, we make use of the authLink in our Apollo client.

Now an Authorization header will be sent along with all requests made to our GraphQL server.

Adding New Post

Posts are the heart of any blog. Users should be able to add new post. Again, we'll first create the GraphQL mutation for add new post to our blog. Add the code below to src/graphql.js:

// src/graphql.js

export const ADD_POST_MUTATION = gql`mutation AddPostMutation($title: String!, $content: String!) {
        addPost(
            title: $title,
            content: $content
        ) {
            id
            slug
            title
            content
            user {
                id
                username
                email
            }
        }
    }`

This mutation takes the title and content of a post we want to add to our GraphQL server.

Next, create a AddPost component within the Admin folder and paste the code below into it:

// src/components/Admin/AddPost.vue

<template>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-3">
                    <Menu/>
                </div>
                <div class="column is-9">
                    <h2 class="title">Add Post</h2>

                    <form method="post" @submit.prevent="addPost">
                        <div class="field">
                            <label class="label">Title</label>

                            <p class="control">
                                <input
                                    class="input"
                                    v-model="title"
                                    placeholder="Post title">
                            </p>
                        </div>

                        <div class="field">
                            <label class="label">Content</label>

                            <p class="control">
                                <textarea
                                    class="textarea"
                                    rows="10"
                                    v-model="content"
                                    placeholder="Post content"
                                    ></textarea>
                            </p>
                        </div>

                        <p class="control">
                            <button class="button is-primary">Add Post</button>
                        </p>
                    </form>
                </div>
            </div>
        </div>
    </section>
</template>

<script>
import Menu from '@/components/Admin/Menu'
import { ADD_POST_MUTATION, ALL_POSTS_QUERY } from '@/graphql'

export default {
    name: 'AddPost',
    components: {
        Menu
    },
    data () {
        return {
            title: '',
            content: ''
        }
    },
    methods: {
        addPost () {
            this.$apollo
                .mutate({
                    mutation: ADD_POST_MUTATION,
                    variables: {
                        title: this.title,
                        content: this.content
                    },
                    update: (store, { data: { addPost } }) => {
                        // read data from cache for this query
                        const data = store.readQuery({ query: ALL_POSTS_QUERY })

                        // add new post from the mutation to existing posts
                        data.allPosts.push(addPost)

                        // write data back to the cache
                        store.writeQuery({ query: ALL_POSTS_QUERY, data })
                    }
                })
                .then(response => {
                    // redirect to all posts
                    this.$router.replace('/admin/posts')
                })
        }
    }
}
</script>

This component renders a form for adding new post. It uses the ADD_POST_MUTATION passing to it the necessary variables. Since Apollo client caches (in memory in our case) it queries, we need a way to update the cache whenever we perform mutation actions. Notice there is an update function which we use to update the store by adding the newly added post to cache. First, we fetch the data from cache matching our query (ALL_POSTS_QUERY), then we add the new post to the allPosts array. Lastly, we write the new data back to cache. Once the post is successfully added, we redirect to the list of posts (which we'll create shortly).

Adding Add Post Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import AddPost from '@/components/Admin/AddPost'

// add these inside the `routes` array
{
    path: '/admin/posts/new',
    name: 'AddPost',
    component: AddPost
}

Users should be able to add new post now:

Displaying Posts

We'll first create the GraphQL query by adding the code below to src/graphql.js:

// src/graphql.js

export const ALL_POSTS_QUERY = gql`query AllPostsQuery {
        allPosts {
            id
            title
            slug
            user {
                username
            }
        }
    }`

This GraphQL query fetches all posts from our GraphQL server.

Next, create a Posts component within the Admin folder and paste the code below into it:

// src/components/Admin/Posts.vue

<template>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-3">
                    <Menu/>
                </div>
                <div class="column is-9">
                    <h2 class="title">Posts</h2>

                    <table class="table is-striped is-narrow is-hoverable is-fullwidth">
                        <thead>
                            <tr>
                                <th>title</th>
                                <th>User</th>
                                <th></th>
                                </tr>
                        </thead>
                        <tbody>
                            <tr
                                v-for="post in allPosts"
                                :key="post.id">
                                    <td>{{ post.title }}</td>
                                    <td>{{ post.user.username }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </section>
</template>

<script>
import Menu from '@/components/Admin/Menu'
import { ALL_POSTS_QUERY } from '@/graphql'

export default {
    name: 'Posts',
    components: {
        Menu
    },
    data () {
        return {
            allPosts: []
        }
    },
    apollo: {
        // fetch all posts
        allPosts: {
            query: ALL_POSTS_QUERY
        }
    }
}
</script>

We make use of the Menu component created earlier. Then we define our data which will be populated once the data is gotten from our GraphQL server. Within the apollo object, we add our GraphQL query to fetch all users. This makes use of the ALL_USERS_QUERY we created above. It is important to note that, the name of our data (allUsers in this case) must be the same name used in our GraphQL query (allUsers in this case). Once allUsers is populated with data from our GraphQL server, we display the users in a table by looping through the array of users. We also add a link to view each user details.

Adding Posts Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import Posts from '@/components/Admin/Posts'

// add these inside the `routes` array
{
    path: '/admin/posts',
    name: 'Posts',
    component: Posts
}

Now when we visit the /admin/posts route, we should see a list of posts as in the image below:

Creating Blog Homepage

The blog homepage will display a list of all posts created just like in the displaying posts section. In fact, the hompage will use the exact same GraphQL used in displaying posts. It is only the markup of the homepage that will be different. Create a Home component inside src/components and add the code below to it:

// src/components/Home.vue

<template>
    <section class="section">
        <div class="columns">
            <div class="column is-6 is-offset-3">
                <h1 class="title">Latest Posts</h1>

                <h3
                    v-for="post in allPosts"
                    :key="post.id"
                    class="title is-5">
                        <router-link :to="post.slug">
                            {{ post.title }}
                        </router-link>
                </h3>
            </div>
        </div>
    </section>
</template>

<script>
import { ALL_POSTS_QUERY } from '@/graphql'

export default {
    name: 'Home',
    data () {
        return {
            allPosts: []
        }
    },
    apollo: {
        // fetch all posts
        allPosts: {
            query: ALL_POSTS_QUERY
        }
    }
}
</script>

As we can see the JavaScript section is identical to that of Posts component. Just different markup. We loop through the posts array and display the title of each post linked with their slug.

Adding Home Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import Home from '@/components/Home'

// add these inside the `routes` array
{
    path: '/',
    name: 'Home',
    component: Home
}

Visiting the / route, we should see our blog homepage as in the image below:

Viewing A Post

The last thing to add is ability to view a specific post. Add the code below to src/graphql.js:

// src/graphql.js

export const POST_QUERY = gql`query PostQuery($slug: String!) {
        post(slug: $slug) {
            id
            title
            slug
            content
            user {
                id
                username
                email
            }
        }
    }`

This query fetch a post by it slug. It takes the slug of the post to be fetched as an argument.

Next, create a SinglePost component inside src/components and add the code below to it:

// src/components/SinglePost.vue

<template>
    <section class="section">
        <div class="columns">
            <div class="column is-6 is-offset-3">
                <router-link class="button is-link is-small" to="/">Back Home</router-link>

                <h1 class="title">
                    {{ post.title }}
                </h1>

                <div class="content">
                    {{ post.content }}
                </div>
            </div>
        </div>
    </section>
</template>

<script>
import { POST_QUERY } from '@/graphql'

export default {
    name: 'SinglePost',
    data () {
        return {
            post: '',
            slug: this.$route.params.slug
        }
    },
    apollo: {
        // fetch post by slug
        post: {
            query: POST_QUERY,
            variables () {
                return {
                    slug: this.slug
                }
            }
        }
    }
}
</script>

We simply display the post title and it content then a link to go back to the homepage. The JavaScript section follows the implementation used in displaying user details. In this case, we get the post slug from the route params.

Adding View Post Route

Open src/router/index.js, and add the code below to it:

// src/router/index.js

import SinglePost from '@/components/SinglePost'

// add these inside the `routes` array
{
    path: '/:slug',
    name: 'SinglePost',
    component: SinglePost,
    props: true
}

Note: This route should be the last route in the routes array.

We should be able to view a single post now:

Conclusion

So, in this tutorial, we have seen how to build a blog app with GraphQL, Apollo client and VueJS. We also saw how to connect our frontend app to a GraphQL server. The complete code for this tutorial is available on GitHub.

Beginner’s Guide to GraphQL with Angular and Apollo

Beginner’s Guide to GraphQL with Angular and Apollo

In this article, we are going to build a small application using Angular and Apollo client

Originally published by Swathi Prasad at https://techshard.com

GraphQL has been gaining popularity and it has made its way to the forefront of API development. There are several GraphQL clients available today for front-end frameworks. Apollo client is one of the popular clients for Angular applications.

Creating Angular Application

Let’s create a new Angular project using Angular CLI. Run the following command in a terminal or command prompt.

ng new angular-apollo –style=scss –routing=true

I have created project with Angular 8 for this tutorial.

Once the project is created, navigate to the project directory angular-apollo in the command prompt or terminal. Add apollo-angular dependency using the command below.

ng add apollo-angular

This command will add following list of dependencies to the project.

"apollo-angular": "^1.6.0",
   "apollo-angular-link-http": "^1.6.0",
   "apollo-cache-inmemory": "^1.3.2",
   "apollo-client": "^2.6.0",
   "apollo-codegen": "^0.20.2",
   "apollo-link": "^1.2.11",
   "graphql": "^14.3.1",
   "graphql-tag": "^2.10.0"

This command would also create a new file graphql.module.ts. This file can be found under /src/app/. In this file, you will find the below line.

const uri = ''; // <-- add the URL of the GraphQL server here

Add this URL http://localhost:8080/graphql to the above line. This is the GraphQL server endpoint which I created in my previous article.

Accessing GraphQL Mutation endpoints in Angular Apollo

The GraphQL server contains the endpoints for creating and reading data for a Vehicle entity. The process that involves write operations is called Mutation. These operations may involve create, update and delete.

The vehicle data model on the server looks like:

type Vehicle {
       id: ID!,
       type: String,
       modelCode: String,
       brandName: String,
       launchDate: String
}

 The mutation endpoint on the server is as below.

type Mutation {
       createVehicle(type: String!, modelCode: String!, brandName: String, launchDate: String):Vehicle
}

Now, we will access this mutation endpoint using Apollo client.

this.apollo.mutate({
     mutation: gql`mutation {
       createVehicle(type: "car", modelCode: "XYZ0192", brandName: "XYZ", launchDate: "2016-08-16") 
        {
         id
       }
     }`
   }).subscribe(data => {
     //successfully created vehicle entity.
   });

I have added the above code in app.component.ts as below. This is the just a basic example to show how the call is made using Apollo client. Note that, we could use services provided by Apollo client for reusability and maintainability.

import { Component, OnInit } from '@angular/core';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

 data: any;

 constructor(private apollo: Apollo) { }

 ngOnInit() {
   this.apollo.mutate({
     mutation: gqlmutation { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createVehicle(type: "car", modelCode: "XYZ0192", brandName: "XYZ", launchDate: "2016-08-16") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
   }).subscribe(data => {
     //successfully created vehicle entity.
   });
 }
}

In this call, we can fetch all the fields from Vehicle object or only a few fields that we need. Here, we are only asking for id field. The server gives back only the id field in the data object.

Querying Data using Apollo Client

As the heading suggests, we will fetch the data using GraphQL query. The query on the server is as follows:

type Query {
       vehicles(count: Int):[Vehicle]
       vehicle(id: ID):Vehicle
}

Using Apollo client, we will access the above the endpoint.

this.apollo.query({
     query: gqlquery { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vehicles(count: 1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modelCode, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;brandName &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
   }).subscribe(({ data, loading }) => {
     this.data = data;
   });

Here, we are interested in only modelCode and brandName fields. The server returns the data with only these fields.

Let’s add a little bit of HTML code to display the data.

 <div class="card" *ngFor="let vehicle of data.vehicles">
   <label class="content">Model: {{ vehicle.modelCode }}</label>
   <label class="content">Brand: {{ vehicle.brandName }}</label>
 </div>
Running the App

Run the application using ng serve. The final app looks like below.


Wrapping Up

We have just scratched the surface of Apollo client. It offers much more features. Check out their documentation for further information.

I hope you enjoyed this article. Let me know if you have any comments or suggestions in the comment section below.

The example for this tutorial can be found on GitHub repository.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Angular 8 (formerly Angular 2) - The Complete Guide

Angular & NodeJS - The MEAN Stack Guide

The Complete Node.js Developer Course (3rd Edition)

Best 50 Angular Interview Questions for Frontend Developers in 2019

React vs Angular: An In-depth Comparison

React vs Angular vs Vue.js by Example

A Beginner’s Guide to GraphQL

Node, Express, PostgreSQL, Vue 2 and GraphQL CRUD Web App

Developing and Securing GraphQL APIs with Laravel