Angular – CRUD operations

By | 27/04/2022

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]

{
  "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:

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]

export interface User {
    id?: number;
    surname: string;
    name: string
}



[CORE.TS]

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 Delete 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]

<header>
    <h1>Users</h1>
    <a routerLink="/manageuser" class="btn" [ngStyle]="{'background-color': 'green'}">Add User</a>
</header>



[USERS.HTML]

<app-useritem *ngFor="let user of users" [user]="user" (onDeleteUser)="deleteUser(user)"></app-useritem>



[USERS.TS]

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]

<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]

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]

<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]

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]

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]

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



Leave a Reply

Your email address will not be published. Required fields are marked *