In this Angular tutorial, we are going to discuss Angular Services. In the Angular Service example tutorial, we will create a Service to perform CRUD (Create, Read, Update and Delete) operations using the HttpClient Angular service.
Services help up managing functions and methods which can be consumed by other components or modules throughout the application. Ideally, use Services to perform network data communications and error handling in an application.
[lwptoc]
Responsibilities of Angular Service Class
- Makes application more organized by keeping reusable methods at one place.
- Makes application easy to maintain and test.
- We can share data between multiple components which are not in direct relation.
- Handling of common operations like CRUD operations, application authentication, creating Auth Guards.
- For keeping simple common methods at one place like date conversion, string formatting, returning boolean expressions etc.
Let’s begin with our example tutorial
Install Angular CLI
To start with the Angular project, first you need to install the latest version of Angular CLI.
$ npm install -g @angular/cli@latest
Create New Angular Project
After that, run the following ng
command to create a new project.
$ ng new angular-service-app ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS
Get inside the project directory
$ cd angular-service-app
Run the application
$ ng serve --open
The --open
flag will open the application in the browser
Create New Angular Service
Next, we will create a new Angular service class that will perform CRUD operations for our demo ToDO application. Create a service by executing the below ng generate
command.
$ ng generate service crud-http
This will create the crud-http.service.ts service with a spec file under the app folder
The crud-http.service.ts file will have the following auto-generated content.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class CrudHttpService {
constructor() { }
}
The @Injectable()
decorator enables a simple Angular class to be provided and get injected as a dependency wherever required.
By default when we create a service the providedIn
is set to 'root'
which provides the services available throughout the application without even providing it inside the App Module. You can check more details on limiting the Service Provider scope here.
Import HttpClientModule
in App Module
To use HttpClient
class methods, first we need to import the HttpClientModule
in the AppModule which is the main module.
Open the app.module.ts file, them update the imports array as shown below:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Now we are ready to update our CrudHttpService
with CRUD methods.
Setup Mock JSON Server
We can easily set up a local mock server by installing the json-server
package. This will help up to quickly test our application performing CRUD operations by using a JSON file.
Step 1) Install json-server
Run the npm command to install the json-server
package globally.
$ npm install -g json-server
Step 2) Create a json file
Next, create a data.json file inside the app/data.json this file will keep the data that will be used for CRUD operations.
Add following property in data.json file
{
"todos":[]
}
Step 3) Start mock server
Finally run the mock server in new CLI instance with json file specified using below command
$ json-server --watch ./src/app/data.json
\{^_^}/ hi!
Loading ./src/app/data.json
Done
Resources
http://localhost:3000/todos
Home
http://localhost:3000
Type s + enter at any time to create a snapshot of the database
Watching...
Following are the API URLs that will be available on our server:
- GET /todos – fetch all todos
- GET /todos/: id – fetch a single todo detail by id
- POST /todos – create a new todo
- PUT /todos/: id – update a todo by id
- PATCH /todos/: id – partially update a todo by id
- DELETE /todos/:id – delete a todo by id
CRUD Method in Service Class
Open the crud-http.service.ts file, then update it with the following code
// crud-http.service.ts
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { catchError } from 'rxjs/operators';
import { Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CrudHttpService {
apiUrl: string = 'http://localhost:3000/todos';
headers = new HttpHeaders().set('Content-Type', 'application/json');
constructor(private http: HttpClient) { }
// Create
create(data: any): Observable<any> {
let API_URL = `${this.apiUrl}`;
return this.http.post(API_URL, data)
.pipe(
catchError(this.handleError)
)
}
// Read
list() {
return this.http.get(`${this.apiUrl}`);
}
// Update
update(id: any, data: any): Observable<any> {
let API_URL = `${this.apiUrl}/${id}`;
return this.http.put(API_URL, data, { headers: this.headers }).pipe(
catchError(this.handleError)
)
}
// Delete
delete(id: any): Observable<any> {
var API_URL = `${this.apiUrl}/${id}`;
return this.http.delete(API_URL).pipe(
catchError(this.handleError)
)
}
// Handle API errors
handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
'Something bad happened; please try again later.');
};
}
Consum Service and CRUD Methods in Component
For accessing the Service methods, import the CrudHttpService service class in constructor
of component file app.component.ts
// app.component.ts
import { Component } from '@angular/core';
import { CrudHttpService } from './crud-http.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(private crudHttpService: CrudHttpService){}
}
Now, we can call our CrudHttpService methods. The listTodo()
method will be called inside the ngOnInit()
hook to show all todo’s by calling the list() service method.
Similerly we have other methods to create, delete, edit or update todo’s in component, which eventually calling our reusable service methods.
import { Component } from '@angular/core';
import { CrudHttpService } from './crud-http.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'angular-service-app';
todoList:any = [];
constructor(private crudHttpService: CrudHttpService){}
ngOnInit(): void {
this.listTodos();
}
listTodos(){
this.crudHttpService.list().subscribe((response)=>{
this.todoList = response;
},(error=>{
}));
}
createTodo(){
let todo = {
id: new Date().getTime(),
title:`Some Todo`
}
this.crudHttpService.create(todo).subscribe((response)=>{
this.listTodos();
},(error=>{
}));
}
editTodo(todo: any){
let data = {
id: new Date().getTime(),
title:`Some Todo`
}
this.crudHttpService.update(todo.id,data).subscribe((response)=>{
this.listTodos();
},(error=>{
}));
}
deleteTodo(id: any){
this.crudHttpService.delete(id).subscribe((response)=>{
this.listTodos();
},(error=>{
}));
}
}
Show the list with action buttons update the app.component.html template with following code.
<div class="container">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let todo of todoList">
<td>{{todo.id}}</td>
<td>{{todo.title}}</td>
<td>
<button type="button" class="btn btn-link" (click)="editTodo(todo)">Edit</button>
<button type="button" class="btn btn-link" (click)="deleteTodo(todo.id)">Delete</button>
</td>
</tr>
</tbody>
</table>
<button type="button" class="btn btn-success" (click)="createTodo()">Create</button>
</div>
Now, run application by hitting $ ng serve --open
or $ npm start
Conclusion
To sum up, we are completed with our Angular Service tutorial. Where we discussed how to create a Service class, then use it to perform CRUD HTTP operations on server data. Although we set up a Mock server using the json-server
, which proves a good tool to replicate real scenarios. But, in a real application, we can simply replace our mock services very easily.