<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 "> Bitovi Blog - UX and UI design, JavaScript and Front-end development

GraphQL & Apollo - An Intro For Angular Developers

Nicole Greene

An introduction to GraphQL and Apollo, including a tutorial on how to query data and connect your service to an Angular application.

posted in Tutorial, Angular, Node.js, GraphQL, Apollo Angular, Apollo on April 26, 2022 by Nicole Greene


GraphQL & Apollo - An Intro For Angular Developers

Nicole Greene by Nicole Greene

Intro

GraphQL is a popular alternative to REST APIs. GraphQL has the potential to simplify and optimize frontend code. In this blog post, we'll demonstrate how to query for data from a GraphQL backend in an Angular application.

What is GraphQL?

GraphQL is “a query language for your API.” Unlike REST APIs, GraphQL only has one endpoint, and developers describe their data using specific parameters, getting back more predictable results. Let’s take a look at an example where we integrate Apollo Client, a JavaScript state management library built to simplify data management from GraphQL queries. We’ll use the cloud platform Apollo Studio to help build our queries.

Launching the Backend With Apollo Studio

Apollo Studio offers a handy user interface to build queries. Let’s take a look at an example server with restaurant data. To follow along, clone the repository and run npm start. When we start the server, we’re presented with a link to Apollo Studio. Here’s what it looks like:

apollo-studio

 

Apollo Studio allows us to build queries by selecting fields we want to be returned. In the example pictured, we are returning all available fields for the “restaurants” query. Imagine we only wanted to query for restaurant names, however. We could omit the rest of the fields. Specificity in queries is one of the advantages of GraphQL and can simplify the returns we get on the frontend.

Overview of the Backend

Now let’s take a look at how we implemented the server in the repository index.js  file where we define our schema, type definitions, and our queries, including the “restaurants” query we mentioned above.

Types

If you’ve used TypeScript, you might notice that GraphQL types are slightly different than TypeScript interfaces. Although they’re not the same thing, the concept of defining the shape of our data is similar. Here’s an example of one of our type definitions for the Restaurant type. It references other custom types such as
RestaurantImageObject:

  type Restaurant {

name: String!
slug: String!
images: RestaurantImageObject
menu: RestaurantMenuObject
address: RestaurantAddressObj
resource: RestaurantImageObject
_id: String
}

Schemas Define Queries and Mutations

Our schema tells Apollo what queries and mutations we have available. In GraphQL, a query represents a call to fetch data from the database. A mutation, on the other hand, handles updating the data, similar to PUT, POST, or DELETE requests as you would use in a REST API. Here are a couple of queries we’ve defined, as well as a mutation to create a restaurant:

  type Query {

restaurants: [Restaurant],
restaurantByName(name: String): Restaurant
}

type Mutation {
createRestaurant(input: CreateRestaurantInput!):
CreateRestaurantResponse
}

Fetching Data With Resolvers

The query resolver in our code is the technique for fetching the types defined in our schema. Our resolvers are shown in the next example (found here in the repo).

const resolvers = {

Query: {
restaurants: () => {
return restaurantData
},
restaurantByName: (_, {name}) => {
return restaurantData.find((restaurant) =>
restaurant.name == name)
}
},
Mutation: {
createRestaurant: (_, {input}) => {
if(!input.name || !input.slug) {
throw new CreateRestaurantError(
'Restaurants must have a name and slug')
}

// Create a random id. Let's use Date.now()
const _id = Date.now().toString()
const restaurant = {
...input,
_id
}
restaurantData.push(restaurant)
return {
__typename: 'CreateRestaurantSuccess',
restaurant: {
name: input.name,
slug: input.slug,
_id
}
}
}
}
};

 

Note the __typename in our response object for the createRestaurant mutation. Imagine instead of returning a success type, we wanted to return a custom error. GraphQL makes that possible, and you can have as many custom error messages as you would like, just be sure to define them in your types.

Fun fact! You might notice that seldom in our server code do we use semicolons. These are actually unnecessary in Node.js due to ES6 automatic semicolon insertion feature.

Running the Angular Frontend

Now that we have a working knowledge of the basics of GraphQL and Apollo, how do we integrate this type of backend with Angular? We can use the well-maintained package Apollo Angular to get things up and running quickly. In the same folder where you cloned the GraphQL repository, clone this repository and run npm ci then npm start to follow along.

Navigating to localhost:4200, we’ll see a navbar UI to interact with the 2 queries and 1 mutation we created in our server.

 angular-application-apollo-example

 

This project comes with Apollo Angular already installed. The other configuration required is including the correct link to our GraphQL API in the graphql.module.ts file. Because we are just running our server locally, we set this to:

const uri = 'http://localhost:4000/';

Ensure that the server is running, and try out our queries and mutations. You should see various results based on your interactions with the UI.

Constructing a Query in the Frontend

We will look at what’s going on in Angular. Before we do that, let’s decide that we want to create a query in our client code to get a restaurant by name. Utilizing the Apollo interface we have running locally at localhost:4000, we can see all of the options currently available on the server side and construct a query to use in our Angular code. In this case we want to return the restaurant’s name and address:

 apollo-query-example

 

Back in the Angular project, the component responsible for this interaction is the Restaurant component, Let’s take a look at restaurant.component.ts at our query getRestaurantByName().



getRestaurantByName() {
this.apollo.query({
query: gql`
query getRestaurantByName($name: String!) {
restaurantByName(name: $name) {
name
address {
street
city
state
}
}
}
`,
variables: {
name: this.restaurantNameForm.value.restaurantName
}
}).subscribe((data: any) => {
const _restaurant = data.data.restaurantByName;
if (!_restaurant) {
if (this.restaurantNameForm.value.restaurantName !== '') {
this.restaurantNameResult$.next(`No restaurants with name ${this.restaurantNameForm.value.restaurantName} were found.`)
} else {
this.restaurantNameResult$.next(`Please type something in the restaurant name field.`)
}
} else {
this.restaurantNameResult$.next(`${_restaurant.name} is located at ${_restaurant.address.street}, ${_restaurant.address.city}, ${_restaurant.address.state}`)
}
})

We use our Apollo and gql imports from apollo-angular to query our server. Remember, there is only one endpoint, which we defined in our graphql file, earlier. We can paste the query we created in Apollo Studio inside the gql string. We also are passing the user input value from the form as our variable.

Then, we subscribe to the data returned by our query. Our example sets the restaurantNameResult$ behavior subject string to include data about the restaurant that was returned, or to an information message if no results were found.

For more guidance on how to construct queries and mutations in Apollo Angular, check out the docs.

Summary

The Apollo platform is beneficial for engineering teams because it simplifies the process of creating queries. This can save tons of development time. On the server side, we have a relatively concise file that allows us to make very precise queries with limited lines of code. On the frontend, we are able to copy and paste our queries from Apollo Studio’s handy interface.

Need GraphQL or Angular development help? Reach out to our team for a free consult!

Create better web applications. We’ll help. Let’s work together.