GraphQL pt 1

Description

GrahpQL [1] means Graph Query Syntax and describes a „protocol“ for your data transfer.

Motivation

Negotiation to an API, an interface between frontend and backend is time-critical. Often both is developed in parallel and the result gets „hacked“ to fit. But a first common data scheme can help.

A good practice for REST-APIs is to choose Swagger [2], so you end up in a well known relational database „create, read, update, delete“-scenario for example.

A modern opponent is a graph API where also most likely a graph database is involved in the backend (to not have an overhead of bending technologies to fit).

So now, to get a setup with Angular and GraphQL, there is already a well evolved library called Apollo Client [3]. Mind the „Simple to get started with“, which is important to not loose the focus in details.

Setup

Via Angular Schematics: ng add apollo-angular

Initial Sample

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { MainPageComponent } from './main-page/main-page.component';
import { FormsModule } from '@angular/forms';
import { GraphQLModule } from './graphql.module';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [MainPageComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    NgbModule,
    GraphQLModule,
    HttpClientModule,
    BrowserModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [MainPageComponent],
})
export class AppModule {}

graph.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { MainPageComponent } from './main-page/main-page.component';
import { GraphQLModule } from './graphql.module';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [MainPageComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    GraphQLModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [MainPageComponent],
})
export class AppModule {}

main-page.component.html

<div class="container">
<h2>Rates</h2>
<ul class="list-group">
  <li *ngFor="let rate of rates | async" class="list-group-item">
    {{rate.currency}}: {{rate.rate}}
  </li>
</ul>

main-page.component.ts

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

const GET_RATES = gql`
  {
    rates(currency: "USD") {
      currency
      rate
    }
  }
`;

@Component({
  selector: 'app-main-page',
  templateUrl: './main-page.component.html',
  styleUrls: ['./main-page.component.scss'],
})
export class MainPageComponent implements OnInit {
  rates: Observable<any>;

  constructor(private apollo: Apollo) {}

  ngOnInit() {
    this.rates = this.apollo
      .watchQuery({
        query: GET_RATES,
      })
      .valueChanges.pipe(map((result) => result.data.rates));
  }
}

Observations

  • graphql.module.ts is a new Angular Module, configuring the data source
  • gql`…`; contains the raw query
  • the apollo client starts this query asynchronously
  • the resulting data is transformed via a pipeline, which is a common pattern for handling async data, here we get support by the libary rxjs [4]
  • currently „result.data.rates“ contains a call to an unkown type, whereas our query actually delivers the data scheme, but probably doesnt spit out a typescript type yet, which would deliver us autocompletion
  • obviously coding contains a lot of „adapt and combine existing solutions“

References

[1] https://graphql.org/learn/
[2] https://swagger.io/resources/articles/best-practices-in-api-design/
[3] https://www.apollographql.com/docs/angular/
[4] http://reactivex.io/rxjs/manual/overview.html


Beitrag veröffentlicht

in

von

Schlagwörter: