loading...

Quick go-to Angular API service setup

lornasw93 profile image Lorna Watson Updated on ・2 min read

I've been playing around with the Deezer API and have found that when working with APIs I tend to use the same layout in terms of project structure.

Alt Text

I always have a pretty simple and generic abstract base service class where contains just 3 methods, purposes being to return individually a item, count and list.

Base API Service

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export abstract class BaseApiService<T> {
  baseUrl = 'https://localhost:44331';

  abstract resourceUrl: string;

  constructor(protected httpClient: HttpClient) { }

  getList(url): Observable<T[]> {
    var to = `${this.baseUrl}/${this.resourceUrl}?${url}`;

    console.log(`GET LIST: ${to}`);
    return this.httpClient.get<T[]>(`${to}`);
  }

  get(url): Observable<T> {
    var to = `${this.baseUrl}/${this.resourceUrl}?${url}`;

    console.log(`GET: ${to}`);
    return this.httpClient.get<T>(`${to}`);
  }

  count(url): Observable<T> {
    var to = `${this.baseUrl}/${this.resourceUrl}?${url}`;

    console.log(`COUNT: ${to}`);
    return this.httpClient.get<T>(`${to}`);
  }
}

Deezer Service

I create service classes that extend from my base abstract, again, keeping it simple.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BaseApiService } from "./base.api.service";
import { Deezer } from "../models/deezer.model";

@Injectable({
  providedIn: 'root'
})
export class DeezerService extends BaseApiService<Deezer> {
  resourceUrl = 'api/Deezer?searchTerm=';

  constructor(http: HttpClient) {
    super(http);
  }

  getSearchResults(query) {
    return this.getList(query);
  }
}

Component

At component level, I pass in an data if required and call the method from the service.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DeezerService } from "../../core/services/deezer.service";

@Component({
  selector: 'app-deezer-search',
  templateUrl: './deezer-search.component.html'
})
export class DeezerSearchComponent implements OnInit { 
  searchResults: any;
  searchForm: FormGroup; 

  constructor(private readonly deezerService: DeezerService,
    private formBuilder: FormBuilder) {
  }

  ngOnInit() {
    this.searchForm = this.formBuilder.group({
      query: ['', Validators.required]
    });
  }

  onSearchSubmit() {
    const query = this.searchForm.value.query;

    this.deezerService.getSearchResults(query).subscribe((data: any) => {
      this.searchResults = data;
    },
      (err) => {
        // handle errors here
      });
  } 
}

To note I've omitted irrelevant bits.

Posted on by:

lornasw93 profile

Lorna Watson

@lornasw93

Full-stack developer based in Leeds

Discussion

markdown guide