Learn how to use GraphQL with Angular using Apollo (Step by Step)

Lukas MarxFebruary 21, 2018

When it comes to angular applications, there is almost always a webserver running an API, as well.

If you have built such an API before, you are probably familiar with the REST-protocol. If you did, you probably also had some issues using it. Certainly, when it comes to more complex queries, REST seems kind of limited.

That is why you should take a look at a GraphQL backend. Other than REST, GraphQL is a full-fledged query language, designed to shine where REST is lacking behind.

It is much more natural to use and also very easy to integrate into your angular application.

In this tutorial, you will learn how to setup your own GraphQL API using node.js and express. Afterwards, we will take a look at how you can easily integrate a GraphQL client into your angular application using apollo-angular.

Let's get started!

GraphQL vs REST

When creating an API, you have the choice of using REST or utilizing a query language like GraphQL.

To do so, you need to know how both of them work and what consequences you will have to deal with.

Either good or bad ones.

The Network-Protocol

First, let's take a look at how both look like a network-level.

REST

REST is fully utilizing the HTTP-protocol.

That means, that request are either get, post, put or delete requests.

For that, it uses an object-oriented endpoint approach, that is modeled using the URL of the resource.

http://example.com/api/blogposts

Depending on the chosen request-method, the request has a different effect.

Get-request are typically used for read-only operations, while post creates a new instance of the chosen object.

Put is used to update an object and delete should delete an object.

For advanced requests, a combination of sub-routes and URL-parameter is used. For example, if we would want to fetch only 10 blog-posts, we would use an URL-parameter like this:

http://example.com/api/blogposts?limit=10

The response of the server is typically a JSON-document.

GraphQL

Often times, GraphQL endpoints use HTTP, as well, but the query language is not limited to that.

It is also possible to use for example the websocket-protocol to transmit the requests over the network.

For a better comparison, let's assume we are using a GraphQL API via HTTP.

GraphQL APIs typically have only one endpoint.

http://example.com/api

All request are sent to that endpoint, independent from the requested object-type (blog-posts) or the desired crud (create, read, update, delete) operation.

They also only use either the HTTP-get or HTTP-post method (one per API) to send the request.

To specify a request, we use the query language itself. The language looks a little bit like JSON, but its syntax is different.

Here is the same example from above for querying 10 blog-posts.

{ blogposts(limit: 10) { title thumbnail content }}

Again, we are using the limit parameter, to limit the number of returned objects.

But while REST typically returns the full object with every field, we have to specify which fields of our object we want to receive using GraphQL.

The response of a GraphQL is a JSON-document.

Overfetching & Underfetching

The above shows example one of the great improvements of GraphQL over REST very nicely. Let's take a look at the reason why.

Again, using our blog-post example, we could have a front-page showing all our blog-post and a detail-page, showing the actual content of each post.

The requirements to the API of both pages are quite different.

While the front-page only requires the title and the thumbnail of each post, the detail page requires all attributes of the post, including the relatively large content.

The problem with a REST-API is a problem called overfetching. Because we can not easily specify which attributes of our blog-posts we want to receive, our blog-application would have to fully download all blog-post to display the front-page.

This results in huge loading times and a lot of unnecessary transferred data.

GraphQL, on the other hand, takes an approach called underfetching. This is exactly what we have seen in the last example. If not explicitly stated, a GraphQL-API does not return any fields of an object. That way, we only get the attributes of our blog-post that we really need.

The request of our front-page could look something like this, only requesting the title and the thumbnail of all posts.

{ blogposts(limit: 10) { title thumbnail }}

The detail-page, on the other hand, is requesting one specific post (e.g. with the id: 1) with all available attributes.

{ blogpost(id: 1) { title thumbnail content }}

Creating a GraphQL API with Express

Now that we know enough about both approaches, you should start implementing your own API-server.

Don't worry! We will discuss the missing parts of GraphQL as we are implementing it.

To set up our node.js server, we will be using the express framework.

Setting up a new Node.js Project

To get started, create a new directory for our new project. You can call it whatever you want.

Next, we initialize a new npm-project by opening the console inside of our new directory and executing the following command:

npm init

It will ask you some questions.Answer them and hit enter, until the setup has finished.

Afterwards, create a new JavaScript file and call it server.js.

We will also need a file named schema.js.

Now go ahead and open both files with your favorite IDE/Editor.

External Dependencies

Before we start coding, we need to install some external dependencies first. That shouldn't take too long.

npm i --save express express-graphql graphql graphql-tools

Here we go! Ready to write some code?

Defining GraphQL Types

Every GraphQL API has a schema. The schema is the definition that defines which resources are available. The schema consists of type-definitions and resolvers.

Our API will have only one resource. The blog-posts. Because GraphQL is a typed language, we first have to define a type for our blog-post. If you are familiar with Typescript, the syntax should look quite familiar.

GraphQL Types

To create the new type, open the schema.js file and add a new variable like this:

The variable typeDefs will contain all our types for our API.Here we have created the type "blog-post". Each blog-post has a set of fields.

Every field has a type, as well. The type is defined after the colon. In this example, all fields are of the type "String".

schema.js

content: String

You can also define if a field is required. To do so, we add an exclamation mark behind the type. For example:

schema.js

id: String!

Input Types

GraphQL differentiates between types for reading and for input purposes. These types are called Input Types and are defined with the input keyword.This is useful because some fields are filled by the server and therefore don't need to be fed in.

In our example, the id of a blog-post can't be defined by the user but is generated by the server automatically. Therefore our input type does not contain a filed called id.

Because we want our API to accept new blog-posts, as well, we add an input called blog-post to our type-definition:

The types inside of that new input type are defined in the same way as a normal type.

Query

The query-type is the root-type of all queries of your API. Inside of that Query-type, we define methods, that can be called via the API.For our example, we want to be able to query for one or for all blog-posts. Because of that, we will need to define two methods inside the query-type.

The definition of query-methods looks quite similar to normal Typescript methods.

The parameters of the method, as well as the return type, are typed in GraphQL. To define an array of a type we place the type in brackets.Notice that we are using our newly created type "blog-post" here.Also, notice that the type "Query" has to be named exactly like this.

Our type-definition is now complete. Go ahead and add methods to update or delete a post if you like!Would you place them into Query or Mutation?

Building GraphQL Resolvers

Now that we have type-definitions, that describe our API, we also need to define some functions, that are triggered, when the defined API-methods are called. These functions are called resolvers and are just JavaScript functions.

To let GraphQL know, which function to call to which API-method, we need to create an object, that has exactly the same structure as our definition.

Next, we need to implement the three functions getAllBlogposts, getBlogpost and addBlogpost that we have registered here.

You can implement these functions however you want. Typically these functions contain a call to the database to filter and receive the requested objects.Once you have the object you want to send back, just return it.

Notice that the returned object needs to have the fields you defined in the type definition.

Here are the three methods for our example. I have created some fake-data, so you can test your API later.

Stay up to date about what is going on in the web-dev community and on this site.

Special offers

Get notified about special offers of our own, or our partners' products. Don't worry, we won't spam your inbox!

Your Email Address

Yes, I want to subscribe to the email newsletter about new articles, products and special offers.

You can change your mind at any time by clicking the unsubscribe link in the footer of any email you
receive from us. For more information about our privacy practices, email performance mesurements, logging of the registration
process and your rights, please take a look at our
Privacy Policy

Join the Newsletter

Never miss a post

Receive updates when a new post is published.

Stay in touch

Stay up to date about what is going on in the web-dev community and on this site.

Special offers

Get notified about special offers of our own, or our partners' products. Don't worry, we won't spam your inbox!

Your Email Address

Yes, I want to subscribe to the email newsletter about new articles, products and special offers.

You can change your mind at any time by clicking the unsubscribe link in the footer of any email you
receive from us. For more information about our privacy practices, email performance mesurements, logging of the registration
process and your rights, please take a look at our
Privacy Policy