In this post, we will see how to create a project in Angular to manage CRUD (Create, Read, Update and Delete) operations for an entity called User; we will use Json Server for the definition of a Web API service.
WEB API
We create a file called UsersDB where we will define a list of User entities:
[USERS.DB]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | { "users" : [ { "id" : 1, "surname" : "Surname1" , "name" : "Name1" }, { "id" : 2, "surname" : "Surname2" , "name" : "Name2" }, { "id" : 3, "surname" : "Surname3" , "name" : "Name3" } ] } |
Now, in order to start Json Server, we run the command:
json-server --watch UsersDB.json
ANGULAR PROJECT
We start defining a new project called UsersCore:
1 | ng new UsersCore |
Then, with the command ng serve, we will run the application:
Now, we create an interface called User and a service called Core, used to define all CRUD operations:
ng g i model/user
ng g s service/core
[USER.TS]
1 2 3 4 5 | export interface User { id?: number; surname: string; name: string } |
[CORE.TS]
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import { Injectable } from '@angular/core' ; import { Observable } from 'rxjs' ; import { User } from '../model/user' ; import { HttpClient, HttpHeaders } from '@angular/common/http' ; // We define the httOptions that we will use in the POST and PUT operations const httpOptions = { headers: new HttpHeaders({ 'Content-Type' : 'application/json' , }), }; @Injectable({ providedIn: 'root' }) export class CoreService { // we define the url of the Web API service private apiUrl: string = "http://localhost:3000/users" ; // we inject the HttpClient constructor( private service: HttpClient) { } // definition of Get operation GetUsers():Observable<User[]>{ return this .service.get<User[]>( this .apiUrl); } // definition of Delete operation DeleteUser(user:User): Observable<User>{ // we pass the User's Id const url = `${ this .apiUrl}/${user.id}`; return this .service. delete <User>(url); } // definition of Update operation UpdateUser(user:User): Observable<User>{ // we pass the User's Id const url = `${ this .apiUrl}/${user.id}`; // We use httpOptions, because we are passing an object return this .service.put<User>(url, user, httpOptions); } // definition of Insert operation AddUser(user:User): Observable<User>{ // We use httpOptions, because we are passing an object return this .service.post<User>( this .apiUrl, user, httpOptions); } } |
Now, we define three components:
1) Header component where we will add the application’s title and a button for adding a new user
2) Users component to display the list of Users
3) UserItem component to display and delete the single User:
ng g c components/header
ng g components/users
ng g c components/useritem
[HEADER.HTML]
1 2 3 4 | < header > < h1 >Users</ h1 > < a routerLink = "/manageuser" class = "btn" [ngStyle]="{'background-color': 'green'}">Add User</ a > </ header > |
[USERS.HTML]
1 | < app-useritem * ngFor = "let user of users" [user]="user" (onDeleteUser)="deleteUser(user)"></ app-useritem > |
[USERS.TS]
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 | import { Component, OnInit } from '@angular/core' ; import { User } from 'src/app/model/user' ; import { CoreService } from 'src/app/service/core.service' ; @Component({ selector: 'app-users' , templateUrl: './users.component.html' , styleUrls: [ './users.component.css' ] }) export class UsersComponent implements OnInit { users: User[] = []; // we inject the CoreService constructor( private userService: CoreService) { } ngOnInit(): void { // in the Init function, we call the GetUsers method this .userService.GetUsers().subscribe(usersOutput => { this .users = usersOutput }); } deleteUser(user: User) { this .userService.DeleteUser(user).subscribe(() => { this .users = this .users.filter(t => t.id!== user.id); }); } } |
[USERITEM.HTML]
1 2 3 4 5 6 | < div class = "user" > < h3 >{{ user.surname }}</ h3 > < p >{{ user.name }}</ p > < button class = "btn" [ngStyle]="{'background-color': 'red'}" (click)="onDelete(user)" >Delete</ button > < button class = "btn" [ngStyle]="{'background-color': 'orange'}" (click)="onUpdate(user)" >Update</ button > </ div > |
[USERITEM.TS]
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 35 36 37 38 39 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core' ; import { User } from 'src/app/model/user' ; import { Router, NavigationExtras } from '@angular/router' ; @Component({ selector: 'app-useritem' , templateUrl: './useritem.component.html' , styleUrls: [ './useritem.component.css' ] }) export class UseritemComponent implements OnInit { @Input() user!:User; @Output() onDeleteUser: EventEmitter<User> = new EventEmitter(); // we inject Router used to pass the value at the manageuser component constructor( private router: Router) { } ngOnInit(): void { } onDelete(user: User){ this .onDeleteUser.emit(user); } onUpdate(user: User) { let navigationExtras: NavigationExtras = { queryParams: { Name: user.name, Surname: user.surname, Id: user.id } }; // we pass the NavigationExtras in the route.navigate this .router.navigate([ "manageuser" ], navigationExtras); } } |
Then, we create a new component called manage-user to manage a user:
ng g c components/manage-user
[MANAGE-USER.HTML]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < form class = "add-form" (ngSubmit)="onSubmit()"> < div class = "form-control" > < label for = "surname" >Surname</ label > < input type = "text" name = "surname" id = "surname" placeholder = "Insert surname" [(ngModel)] = "surname" /> </ div > < div class = "form-control" > < label for = "name" >Name</ label > < input type = "text" name = "name" id = "name" placeholder = "Insert name" [(ngModel)] = "name" /> </ div > < div class = "btn-group" > < input type = "submit" value = "Save User" class = "btn" style = "width: 110px;" > < a routerLink = "/users" class = "btn" [ngStyle]="{'background-color': 'red'}">Cancel</ a > </ div > </ form > |
[MANAGE-USER.TS]
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import { Component, OnInit, Input } from '@angular/core' ; import { User } from 'src/app/model/user' ; import { CoreService } from 'src/app/service/core.service' ; import { Router, ActivatedRoute } from '@angular/router' ; @Component({ selector: 'app-manage-user' , templateUrl: './manage-user.component.html' , styleUrls: [ './manage-user.component.css' ] }) export class ManageUserComponent implements OnInit { id?:number; surname: string = "" ; name: string = "" ; // we inject userService used to call the AddUser and UpdateUser methods // router is used to redirect the page at the list of users // activatedRoute is used to get the parameters from the previuos page, in case of update constructor( private userService: CoreService, private router: Router, private activatedRoute: ActivatedRoute){ // using activatedRoute we can get the parameters // that we put in the previous page this .activatedRoute.queryParams.subscribe(params => { this .name = params[ 'Name' ]; this .surname = params[ 'Surname' ]; this .id = params[ 'Id' ]; }); } ngOnInit(): void { } onSubmit(){ if (! this .surname || ! this .name) { alert( 'Please insert Surname and Name!' ); return } const outputUser: User = { name: this .name, surname: this .surname }; if ( this .id === undefined) { // new user this .userService.AddUser(outputUser).subscribe(); } else { // update user outputUser.id = this .id; this .userService.UpdateUser(outputUser).subscribe(); } // redirect to the Users list page this .router.navigate([ '/' ]); } } |
Finally, we have to modify other two files:
[APP-ROUTING.TS]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import { NgModule } from '@angular/core' ; import { RouterModule, Routes } from '@angular/router' ; import { UsersComponent } from './components/users/users.component' ; import { ManageUserComponent } from './components/manage-user/manage-user.component' ; const routes: Routes = [ { path: '' , pathMatch: 'full' , redirectTo: 'users' }, { path: 'users' , component: UsersComponent }, { path: 'manageuser' , component: ManageUserComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } |
[APP.MODULE.TS]
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 | import { NgModule } from '@angular/core' ; import { BrowserModule } from '@angular/platform-browser' ; import { HttpClientModule } from '@angular/common/http' import { FormsModule } from '@angular/forms' ; import { AppRoutingModule } from './app-routing.module' ; import { AppComponent } from './app.component' ; import { HeaderComponent } from './components/header/header.component' ; import { UsersComponent } from './components/users/users.component' ; import { UseritemComponent } from './components/useritem/useritem.component' ; import { ManageUserComponent } from './components/manage-user/manage-user.component' ; @NgModule({ declarations: [ AppComponent, HeaderComponent, UsersComponent, UseritemComponent, ManageUserComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } |
We have done and now, if we run the application, this will be the result:
LIST OF USERS
NEW USER
UPDATE USER
DELETE USER
CRUD operations – CODE
https://github.com/ZoneOfDevelopment/AngularCRUDOperations