Once you’ve created the interface for the Categories section, now it’s time to call the APIs of the API Category Service to add, remove, edit, and display all categories. In this tutorial, I will guide the first step is to display all categories using Angular.
First, I will write a CategoriesService class to make the API call to retrieve all categories of the API Category Service.
To do this, first I will create a new class called CategoriesService located in the src/app/services directory as follows:
This class will be injected into the CategoriesComponent class to use, so we will declare it with the @Injectable decorator as follows:
1 2 3 4 5 6 |
import { Injectable } from "@angular/core"; @Injectable() export class CategoriesService { } |
Next, we will create a new Category object to contain the category information that the API will return as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import { Injectable } from "@angular/core"; @Injectable() export class CategoriesService { } export class Category { id: string; name: string; code: string; description: string; } |
To be able to call the API to retrieve all categories of the API Category Service, I would declare using the Angular HttpClient object as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import { Injectable } from "@angular/core"; @Injectable() export class CategoriesService { constructor(private http: HttpClient) { } } export class Category { id: string; name: string; code: string; description: string; } |
Now, I can write a method to retrieve all the categories from the API Category Service:
1 2 3 |
findAllCategories(): Promise<Category[]> { return this.http.get<Category[]>("/category/all").toPromise(); } |
As you can see, here I am not declaring baseUrl of the API Category Service. This is because both the API Category Service and the Frontend of the current Question Management application will run on the local machine. This will cause a Cross-Origin Resource Sharing (CORS) vulnerability if you run our application using a Chrome browser or some other application. You can find out more about this error on the internet.
To ignore this error, you can simulate our Frontend application when calling APIs of services through a proxy, by creating a new proxy.conf.json file in the Frontend project directory with the following content:
1 2 3 4 5 6 7 |
{ "/category/*": { "target": "http://localhost:8282", "secure": false, "logLevel": "debug" } } |
With this declaration, outbound requests with URLs beginning with “/category” will be requested to http://localhost:8282, which is the address of the API Category Service. In the future, when we deploy our application to production, we need to revise this part.
To use this class, we need to declare it in the AppModule class, in the provider attribute of the @NgModule decorator. We also need to declare import HttpClientModule:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { NavigationModule } from './navigation/navigation.module'; import { DashboardModule } from './dashboard/dashboard.module'; import { AppRoutingModule } from './app-routing.module'; import { QuestionsModule } from './questions/questions.module'; import { CategoriesService } from './services/categories.service'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule, AppRoutingModule, NavigationModule, DashboardModule, QuestionsModule ], providers: [ CategoriesService ], bootstrap: [ AppComponent ] }) export class AppModule { } |
OK, now we will use the CategoriesService class to get all the existing categories to display on the table in the Categories interface.
To do this, we first declare to use the CategoriesService class in the constructor part of CategoriesComponent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { Component, AfterViewInit } from "@angular/core"; import { CategoriesService } from "../../services/categories.service"; declare var $: any; @Component({ selector: 'qm-body', templateUrl: './categories.component.html' }) export class CategoriesComponent implements AfterViewInit { constructor(private categoriesService: CategoriesService) { } ngAfterViewInit(): void { $('#dataTables-categories').DataTable({ responsive: true }); } } |
then, I would define a category variable to contain all categories after retrieving the API from the API Category Service.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import { Component, AfterViewInit } from "@angular/core"; import { CategoriesService, Category } from "../../services/categories.service"; declare var $: any; @Component({ selector: 'qm-body', templateUrl: './categories.component.html' }) export class CategoriesComponent implements AfterViewInit { categories: Category[]; constructor(private categoriesService: CategoriesService) { } ngAfterViewInit(): void { $('#dataTables-categories').DataTable({ responsive: true }); } } |
Now we can write code using the findAllCategories() method of the CategoriesService to get all the categories:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import { Component, AfterViewInit } from "@angular/core"; import { CategoriesService, Category } from "../../services/categories.service"; declare var $: any; @Component({ selector: 'qm-body', templateUrl: './categories.component.html' }) export class CategoriesComponent implements AfterViewInit { categories: Category[]; constructor(private categoriesService: CategoriesService) { } showAllCategories() { this.categoriesService.findAllCategories().then(r => { this.categories = r; setTimeout(function() { $('#dataTables-categories').DataTable({ responsive: true }); }, 100); }); } ngAfterViewInit(): void { this.showAllCategories(); } } |
To display these categories, in the categories.component.html file, the table section displays the category list, I will edit as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<table width="100%" class="table table-striped table-bordered table-hover" id="dataTables-categories"> <thead> <tr> <th>Name</th> <th>Code</th> <th>Description</th> <th>Actions</th> </tr> </thead> <tbody> <tr *ngFor="let category of categories; let odd = odd; let even = even" [ngClass]="{ odd: odd, even: even }"> <td>{{ category.name }}</td> <td>{{ category.code }}</td> <td>{{ category.description }}</td> <td> <button type="button" class="btn btn-warning btn-circle"><i class="fa fa-edit"></i></button> <button type="button" class="btn btn-danger btn-circle"><i class="fa fa-trash"></i></button> </td> </tr> </tbody> </table> <!-- /.table-responsive --> |
We need to declare the CommonModule in the QuestionsModule module to use the Angular directive which we used above as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import { NgModule } from "@angular/core"; import { CategoriesComponent } from "./categories/categories.component"; import { CommonModule } from "@angular/common"; @NgModule({ declarations: [ CategoriesComponent ], imports: [ CommonModule ], exports: [ CategoriesComponent ] }) export class QuestionsModule { } |
OK, everything has done, now try it.
Here, we need to run the Angular application with the proxy.conf.json file as follows:
1 |
ng serve --proxy-config proxy.conf.json |
Suppose now in the database I have the following categories:
now, if you run the application you will see the list of categories is displayed as follows: