Integrating GraphQL into Angular Apps with Apollo Client
Effectively handling data is crucial for creating responsive applications. While traditional REST APIs have been widely used, the emergence ofGraphQLoffers developers a potent alternative.Angular, a popular web application framework, can seamlessly harness the capabilities of GraphQL throughApollo Client.
Overview of Apollo Client
Apollo Client is a state management library designed for JavaScript applications, particularly those leveraging GraphQL APIs. It offers a suite of functionalities including caching, local state management, and reactive data fetching, providing a powerful means to manage application data and state. Developed by the creators of Apollo GraphQL, it streamlines the integration of GraphQL into front-end applications by offering a cohesive interface for querying and managing data. Compatible with major frontend frameworks like React, Angular, and Vue.js, Apollo Client stands as a versatile solution for crafting contemporary web applications.
Benefits of using Apollo Client include:
Efficient Data Fetching: Apollo Client simplifies data fetching by providing a powerful and flexible GraphQL client that efficiently fetches data from a server. It optimizes data fetching by fetching only the data required by the client, minimizing unnecessary requests.
Declarative Data Management: Apollo Client offers a declarative approach to data management, allowing developers to specify data requirements using GraphQL queries directly within their Angular components. This approach enhances code readability and maintainability.
Normalized Cache: Apollo Client maintains a normalized cache that stores fetched data in a normalized form. This cache improves performance by eliminating redundant data and facilitating efficient retrieval and updates.
Real-time Data Updates: Apollo Client seamlessly integrates with GraphQL subscriptions, enabling real-time data updates in Angular applications. This feature is useful for building interactive applications that require instant updates based on server-side changes.
Client-side State Management: Apollo Client supports client-side state management, allowing developers to manage local application state alongside remote data. This feature enables centralized state management within Angular applications, simplifying data synchronization and improving scalability.
Community Support and Ecosystem: Apollo Client benefits from a thriving community and ecosystem, with extensive documentation, tutorials, and community support available. This ecosystem includes tools, plugins, and integrations that enhance the development experience and address common use cases.
Setting up the Development Environment
To start, initiate a new Angular project using any desired file name. To create the project, execute the following command:
ng new <file name>
Then, navigate into the newly generated directory:
cd <file name>
Subsequently, install the apollo-angular
dependency:
ng add apollo-angular
Upon installing the apollo-angular
dependency, you will be prompted to specify the URL
of your GraphQL API. For demonstration purposes, we will utilize a free API available at “https://countries.trevorblades.com/graphql”. You have the option to develop your own GraphQL API utilizing Node.js. Detailed instructions on how to do so can be found in our previous post, where we walk you through the process step by step.
To modify the GraphQL API, access the graphql.provider.ts
file and update the following line of code with your preferred API:
const uri = ' insert your preferred API ';
Next, navigate to the app.component.ts
file and import the following dependencies:
import { gql, Apollo } from 'apollo-angular';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
Then, add FormsModule
and CommonModule
into the import array within the @Component
class:
@Component({
// other metadata
imports: [RouterOutlet, CommonModule, FormsModule],
})
Integrating GraphQL into Angular Apps
To integrate GraphQL into our Angular application, we'll start by creating a GraphQL service using Apollo Client. Define a GraphQL query to fetch data.
const Get_MyCountries = gql`
query Query {
country(code: "NG") {
name
native
capital
emoji
currency
}
}`
Next, in the src
folder of our project, create a sub-folder named model
. Within this sub-folder, create a new file named country.ts
. In this TypeScript file, we'll define the structure of the data that our application will utilize. Here's an example of how to define the Country
interface:
export interface Country {
name: string;
native: string;
capital: string;
emoji: string;
currency: string;
}
This structure will help us maintain a clear and consistent data model throughout our Angular application.
Implementing GraphQL queries
We would implement GraphQL queries in our Angular component for fetching data from a GraphQL API endpoint.
Firstly, within the AppComponent
class, we implement the OnInit interface to ensure that the necessary initialization steps occur. Also, create a property country
of type Country
which we earlier created.
export class AppComponent implements OnInit {
country!: Country;
ngOnInit(): void {
// Initialization logic here
}
}
Within the constructor of the AppComponent
class, we initialize an instance of the Apollo
class. This instance, named apollo
, is a private property of the class and facilitates interaction with the Apollo Client service, which handles GraphQL operations.
export class AppComponent implements OnInit {
country!: Country;
constructor(private apollo: Apollo) {}
ngOnInit(): void {
// Initialization logic here
}
}
In the ngOnInit()
method, we execute a GraphQL query to the server by utilizing Apollo Client's watchQuery
method. This method requires an options object as an argument, where the query
property is set to Get_MyCountries
, representing the predefined GraphQL query.
export class AppComponent implements OnInit {
country!: Country;
constructor(private apollo: Apollo) {}
ngOnInit(): void {
this.apollo
.watchQuery<any>({
query: Get_MyCountries
})
// Subscription logic here
}
}
Subsequently, we subscribe to the observable returned by watchQuery
, which emits changes in data or loading state. The callback function of the subscription receives an object containing data
and loading
. Within this function, we validate whether loading
is false
and whether both data
and data.country
is true. If these conditions are met, we extract country data from data.country
and assign it to the country
property of the component.
export class AppComponent implements OnInit {
country!: Country;
constructor(private apollo: Apollo) {}
ngOnInit(): void {
this.apollo
.watchQuery<any>({
query: Get_MyCountries
})
.valueChanges.subscribe(({ data, loading }) => {
if (!loading && data && data.country) {
this.country = {
name: data.country.name,
native: data.country.native,
capital: data.country.capital,
emoji: data.country.emoji,
currency: data.country.currency
};
}
});
}
}
Displaying data using templates
To display the fetched data in the DOM, we'll utilize a Bootstrap table template. First, ensure the Bootstrap CSS is linked in the index.html
file by adding the Bootstrap CDN link:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
Then, create a table element in your HTML template and apply Bootstrap styling classes like table
and table-hover
to enhance its visual appeal. Use the *ngIf
directive to conditionally render the table only when there is valid country data available:
<table class="table table-hover" *ngIf="country">
Define the table headers (thead
) within the table element. Each table header (th
) represents a column in the table. Specify the headers for the country information you want to display, such as name, native name, capital, emoji, and currency:
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Native</th>
<th scope="col">Capital</th>
<th scope="col">Emoji</th>
<th scope="col">Currency</th>
</tr>
</thead>
After defining the table headers, create the table body (tbody
) section. Inside the tbody
, define a table row (tr
) and its corresponding cells (td
). Use Angular interpolation ({{ }}
) to display the country information fetched from the country
object provided by the component:
<tbody>
<tr>
<td>{{ country.name }}</td>
<td>{{ country.native }}</td>
<td>{{ country.capital }}</td>
<td>{{ country.emoji }}</td>
<td>{{ country.currency }}</td>
</tr>
</tbody>
In each table cell, access the specific property of the country
object to display its name, native name, capital, emoji, and currency. Ensure that the country
object is properly initialized and passed to the template from the component.
Finally, here's a snapshot of the data fetched from the GraphQL API.
Conclusion
Integrating GraphQL into Angular apps with Apollo Client offers developers a streamlined approach to managing data and state. With features like efficient data fetching, declarative data management, and real-time updates, Apollo Client simplifies working with GraphQL APIs in Angular projects. By leveraging these technologies, developers can build responsive web applications with ease.
Additional Resources
Subscribe to my newsletter
Read articles from Marydera Ugorji directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by