Build an Angular 14 CRUD Example & Tutorial

Build an Angular 14 CRUD Example & Tutorial

In this tutorial, we'll learn to build an Angular CRUD example from scratch using the latest version which is as the time of this writing Angular 14.

We'll be using a CRUD REST API mocked using json-server which lets you generate a complete working API with nearly zero-lines of code.

We'll not be learning how to use json-server but you can see the complete instructions from this tutorial after generating the Angular project.

  • Step 1 — Mocking the Backend Using json-server
  • Step 2 — Creating an Angular 14 Module
  • Step 3 — Importing Angular HttpClientModule and FormsModule
  • Step 4 — Creating Angular Component(s)
  • Step 5 — Adding Angular Routing
  • Step 6 — Creating an Angular Service
  • Step 7 — Creating a Model
  • Step 8 — Implementing the CRUD Methods
  • Step 9 — Calling the CRUD Methods

Prerequisites

As always, we'll need to have a few prerequisites for this tutorial:

  • The basic concepts of TypeScript and JavaScript.
  • A local development machine with Node 10+, together with NPM installed.
  • Angular CLI 14 installed on your machine,
  • An Angular project. In our case, it's named angular14crudexample.

If your project is ready, let's get started with our first step.

Angular CRUD Example, Step 1 — Mocking the Backend Using json-server

We have already covered how to mock the REST API in Mocking a REST API Back-End for Your Angular App with JSON-Server and Faker.js

You can simply follow the linked tutorial to quickly build a server that will be running from the http://localhost:3000 address and exposing the following endpoints:

  • GET /products for getting the products,
  • GET /products/<id> for getting a single product by id,
  • POST /products for creating a new product,
  • PUT /products/<id> for updating a product by id,
  • PATCH /products/<id> for partially updating a product by id,
  • DELETE /products/<id> for deleting a product by id.

Angular CRUD

Step 2 — Creating an Angular 14 Module

We'll encapsulate the code for our CRUD interface inside a module called crud. Open a new command-line interface and generate a module using the following command:

$ cd ~/angular14crudexample
$ ng generate module crud --routing

This will create a src/app/crud/crud.module.ts file with the following code:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { CrudRoutingModule } from './crud-routing.module';


@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    CrudRoutingModule
  ]
})
export class CrudModule { }

Step 3 — Importing Angular 14 HttpClientModule and FormsModule

In this step, we'll proceed to add HttpClientModule and FormsModule in our project so we can use HttpClient and forms to implement the CRUD operations against the API server.

Open the src/app/crud/crud.module.ts file and add HttpClientModuleand FormsModuleto the imports array of the module as follows:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';

import { CrudRoutingModule } from './crud-routing.module';


@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    CrudRoutingModule,
    HttpClientModule,
    FormsModule
  ]
})
export class CrudModule { }

Step 4 — Creating Angular 14 Component(s)

In this step, we'll create the Angular components. that compose the UI of our CRUD application:

  • A home component that renders a table of products and contains the CRUD operations,
  • A details component that displays the details of a specific product,
  • A create component for creating products,
  • A update component for updating products.

Open a new command-line interface and run the following commands:

$ ng generate component crud/home
$ ng generate component crud/details
$ ng generate component crud/create
$ ng generate component crud/update

The CLI will create the necessary files for the components and add them to the declarations array in the src/app/crud/crud.module.ts file:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

import { CrudRoutingModule } from './crud-routing.module';
import { HomeComponent } from './home/home.component';
import { DetailsComponent } from './details/details.component';
import { CreateComponent } from './create/create.component';
import { UpdateComponent } from './update/update.component';


@NgModule({
  declarations: [HomeComponent, DetailsComponent, CreateComponent, UpdateComponent],
  imports: [
    CommonModule,
    CrudRoutingModule,
    HttpClientModule
  ]
})
export class CrudModule { }

Step 5 — Adding Angular 14 Routing

In this step, we'll add routing. to our CRUD module.

Head back to the src/app/crud/crud-routing.module.ts file, that was automatically created by Angular CLI for routing configuration, and import the components then add the routes as follows:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { DetailsComponent } from './details/details.component';
import { CreateComponent } from './create/create.component';
import { UpdateComponent } from './update/update.component';

const routes: Routes = [
  { path: 'crud', redirectTo: 'crud/home', pathMatch: 'full'},
  { path: 'crud/home', component: HomeComponent },
  { path: 'crud/details/:productId', component: DetailsComponent },
  { path: 'crud/create', component: CreateComponent },
  { path: 'crud/update/:productId', component: UpdateComponent } 
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

We first imported the CRUD components, next we added five routes for each component and a redirection route which simply redirects users to the home component when they visit the empty path.

In the next step of our example, we'll a service for crud methods.

Step 6 — Creating an Angular 14 Service

In this step, we'll create an an Angular service that encapsulates the CRUD operations and make them available to the various UI components.

Go back to your command-line interface and run the following command:

$ ng generate service crud/crud

Next, open the src/app/crud/crud.service.ts file, and import and inject HttpClient as follows:

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

@Injectable({
  providedIn: 'root'
})
export class CrudService {

  private apiServer = "http://localhost:3000";

  constructor(private httpClient: HttpClient) { }
}

We imported and injected the HttpClient service. We also defined the apiServer variable that contains the address of our REST API server.

Step 7 — Creating an Angular 14 Model

In this step, we'll see how to create a model for using typed HTTP responses in our example.

Head back to your command-line interface and run the following command from the root of your project:

$ ng generate interface  crud/product

Next, open the src/app/crud/product.ts file and update it as follows:

export interface Product {
    id: number;
    name: string;
    description: string;
    price: number;
    quantity: number;
}

Step 8 — Implementing the CRUD Methods

Let's now implement the CRUD operations for creating, reading. updating and deleting products using a service.

Open the src/app/crud/crud.service.ts file and update it as follows:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";

import {  throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

import { Product } from './product';

@Injectable({
  providedIn: 'root'
})
export class CrudService {

  private apiServer = "http://localhost:3000";
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  }
  constructor(private httpClient: HttpClient) { }

  create(product): Observable<Product> {
    return this.httpClient.post<Product>(this.apiServer + '/products/', JSON.stringify(product), this.httpOptions)
    .pipe(
      catchError(this.errorHandler)
    )
  }  
  getById(id): Observable<Product> {
    return this.httpClient.get<Product>(this.apiServer + '/products/' + id)
    .pipe(
      catchError(this.errorHandler)
    )
  }

  getAll(): Observable<Product[]> {
    return this.httpClient.get<Product[]>(this.apiServer + '/products/')
    .pipe(
      catchError(this.errorHandler)
    )
  }

  update(id, product): Observable<Product> {
    return this.httpClient.put<Product>(this.apiServer + '/products/' + id, JSON.stringify(product), this.httpOptions)
    .pipe(
      catchError(this.errorHandler)
    )
  }

  delete(id){
    return this.httpClient.delete<Product>(this.apiServer + '/products/' + id, this.httpOptions)
    .pipe(
      catchError(this.errorHandler)
    )
  }
  errorHandler(error) {
     let errorMessage = '';
     if(error.error instanceof ErrorEvent) {
       // Get client-side error
       errorMessage = error.error.message;
     } else {
       // Get server-side error
       errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
     }
     console.log(errorMessage);
     return throwError(errorMessage);
  }
}

Step 9 — Calling the Angular 14 CRUD Methods

Next, let's see how to make CRUD operations in our components. Open the src/app/crud/home/home.component.ts file, import and inject the Angular service as follows:

import { Component, OnInit } from '@angular/core';
import { CrudService } from '../data.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  products: Products[] = [];

  constructor(public crudService: CrudService) { }

  ngOnInit() {

    this.crudService.getAll().subscribe((data: Products[])=>{
      console.log(data);
      this.products = data;
    })  
  }

}

We imported and injected CrudService as a private crudService instance via the component constructor.

Next, we defined a products array and invoked the getAll() method for making a read operation against the API server.

Next, open the src/app/crud/home/home.component.html file and update it as follows:

            <div>
                <h1>My Products</h1>
                <button type="button" [routerLink]="/crud/create/">Create new product</button>
                <table>
                    <thead>
                        <tr>
                            <th>#</th>
                            <th>Product Name</th>
                            <th>Description</th>
                            <th>Price</th>
                            <th>Quantity</th>                            
                            <th>Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr *ngFor="let product of products">
                            <td>{{product.id}}</td>
                            <td>{{product.name}}</td>
                            <td>{{product.description}}</td>
                            <td>{{product.quantity}}</td>
                            <td>
                                <button type="button" [routerLink]="['/crud/update/', product.id]">Update</button>
                                <button type="button" (click)="crudService.delete(product.id)">Remove</button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>

We iterated over the products array using the ngFor directive and displayed the name, price, quantity, and description of each product. And we added two buttons for running the delete operations and navigating to the update component where we can run the update operation.

We also added a button for navigation the user to the product creation component.

Next, open the src/app/crud/create/create.component.ts file and update it as follows to create an angular form:

import { Component, OnInit } from '@angular/core';
import { CrudService } from '../crud.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})

export class CreateComponent implements OnInit {
  productForm: FormGroup;

  ngOnInit() {
      this.productForm = this.fb.group({
      name: [''],
      description: [''],
      price: [''],
      quantity: [''],    
    })
  }

  constructor(
    public fb: FormBuilder,
    private router: Router,
    public crudService: CrudService
  ){ }
  submitForm() {
    this.crudService.create(this.productForm.value).subscribe(res => {
      console.log('Product created!')
      this.router.navigateByUrl('/crud/home/'))

  }

}

Next, open the src/app/crud/create/create.component.html and add the following HTML form for creating a product:

 <div>
            <h1>Create Product</h1>
            <form [formGroup]="productForm" (ngSubmit)="submitForm()" novalidate>
                <div class="form-group">
                    <label>Name</label>
                    <input type="text" formControlName="name" class="form-control" maxlength="20">
                </div>
                <div class="form-group">
                    <label>Description</label>
                    <textarea class="form-control" formControlName="description" rows="3" maxlength="50"></textarea>
                </div>
                <div class="form-group">
                    <label>Price</label>
                    <input type="text" formControlName="price" class="form-control">
                </div>
                <div class="form-group">
                    <label>Quantity</label>
                    <input type="text" formControlName="quantity" class="form-control">
                </div>
                <button type="submit">Submit</button>
            </form>
</div>

The implementation of the update operation is left as an exercise for the reader. It's quite similar to the create operation except that we need to retrieve the ID of the product to update from the route parameter.

We have implemented the read operation for getting all the products but you also need to read a product by ID.

Conclusion

In this tutorial, we've built a CRUD example using the latest Angular 14 version.

We have created a service and implemented the create, read, update and delete operations against a REST API backend with a fake JSON database.



Create Angular 17 Project
Building a Password Strength Meter in Angular 17
Angular 17 Password Show/Hide with Eye Icon
Angular 17 tutoriel
Angular Select Change Event
Angular iframe
Angular FormArray setValue() and patchValue()
Angular Find Substring in String
Send File to API in Angular 17
EventEmitter Parent to Child Communication
Create an Angular Material button with an icon and text
Input change event in Angular 17
Find an element by ID in Angular 17
Find an element by ID from another component in Angular 17
Find duplicate objects in an array in JavaScript and Angular
What is new with Angular 17
Style binding to text-decoration in Angular
Remove an item from an array in Angular
Remove a component in Angular
Delete a component in Angular
Use TypeScript enums in Angular templates
Set the value of an individual reactive form fields
Signal-based components in Angular 17
Angular libraries for Markdown: A comprehensive guide
Angular libraries for cookies: A comprehensive guide
Build an Angular 14 CRUD Example & Tutorial
Angular 9 Components: Input and Output
Angular 13 selectors
Picture-in-Picture with JavaScript and Angular 10
Jasmine Unit Testing for Angular 12
Angular 9 Tutorial By Example: REST CRUD APIs & HTTP GET Requests with HttpClient
Angular 10/9 Elements Tutorial by Example: Building Web Components
Angular 10/9 Router Tutorial: Learn Routing & Navigation by Example
Angular 10/9 Router CanActivate Guards and UrlTree Parsed Routes
Angular 10/9 JWT Authentication Tutorial with Example
Style Angular 10/9 Components with CSS and ngStyle/ngClass Directives
Upload Images In TypeScript/Node & Angular 9/Ionic 5: Working with Imports, Decorators, Async/Await and FormData
Angular 9/Ionic 5 Chat App: Unsubscribe from RxJS Subjects, OnDestroy/OnInit and ChangeDetectorRef
Adding UI Guards, Auto-Scrolling, Auth State, Typing Indicators and File Attachments with FileReader to your Angular 9/Ionic 5 Chat App
Private Chat Rooms in Angular 9/Ionic 5: Working with TypeScript Strings, Arrays, Promises, and RxJS Behavior/Replay Subjects
Building a Chat App with TypeScript/Node.js, Ionic 5/Angular 9 & PubNub/Chatkit
Chat Read Cursors with Angular 9/Ionic 5 Chat App: Working with TypeScript Variables/Methods & Textarea Keydown/Focusin Events
Add JWT REST API Authentication to Your Node.js/TypeScript Backend with TypeORM and SQLite3 Database
Building Chat App Frontend UI with JWT Auth Using Ionic 5/Angular 9
Install Angular 10 CLI with NPM and Create a New Example App with Routing
Styling An Angular 10 Example App with Bootstrap 4 Navbar, Jumbotron, Tables, Forms and Cards
Integrate Bootstrap 4/jQuery with Angular 10 and Styling the UI With Navbar and Table CSS Classes
Angular 10/9 Tutorial and Example: Build your First Angular App
Angular 9/8 ngIf Tutorial & Example
Angular 10 New Features
Create New Angular 9 Workspace and Application: Using Build and Serve
Angular 10 Release Date: Angular 10 Will Focus on Ivy Artifacts and Libraries Support
HTML5 Download Attribute with TypeScript and Angular 9
Angular 9.1+ Local Direction Query API: getLocaleDirection Example
Angular 9.1 displayBlock CLI Component Generator Option by Example
Angular 15 Basics Tutorial by Example
Angular 9/8 ngFor Directive: Render Arrays with ngFor by Example
Responsive Image Breakpoints Example with CDK's BreakpointObserver in Angular 9/8
Angular 9/8 DOM Queries: ViewChild and ViewChildren Example
The Angular 9/8 Router: Route Parameters with Snapshot and ParamMap by Example
Angular 9/8 Nested Routing and Child Routes by Example
Angular 9 Examples: 2 Ways To Display A Component (Selector & Router)
Angular 9/8 Tutorial: Http POST to Node/Express.js Example
Angular 9/8 Feature and Root Modules by Example
Angular 9/8 with PHP: Consuming a RESTful CRUD API with HttpClient and Forms
Angular 9/8 with PHP and MySQL Database: REST CRUD Example & Tutorial
Unit Testing Angular 9/8 Apps Tutorial with Jasmine & Karma by Example
Angular 9 Web Components: Custom Elements & Shadow DOM
Angular 9 Renderer2 with Directives Tutorial by Example
Build Progressive Web Apps (PWA) with Angular 9/8 Tutorial and Example
Angular 9 Internationalization/Localization with ngx-translate Tutorial and Example
Create Angular 9 Calendar with ngx-bootstrap datepicker Example and Tutorial
Multiple File Upload with Angular 9 FormData and PHP by Example
Angular 9/8 Reactive Forms with Validation Tutorial by Example
Angular 9/8 Template Forms Tutorial: Example Authentication Form (ngModel/ngForm/ngSubmit)
Angular 9/8 JAMStack By Example
Angular HttpClient v9/8 — Building a Service for Sending API Calls and Fetching Data
Styling An Angular 9/8/7 Example App with Bootstrap 4 Navbar, Jumbotron, Tables, Forms and Cards

✋If you have any questions about this article, ask them in our GitHub Discussions 👈 community. You can also Gitter

✋ Want to master Angular 14? Read our angular tutorial and join our #DailyAngularChallenge where we learn to build components, directives, services, pipes and complete web, mobile, and desktop applications with latest Angular version.

✋ Make sure to join our Angular 14 Dev Community 👈 to discuss anything related to Angular development.

❤️ Like our page and subscribe to our feed for updates!

Find a list of emojis to copy and paste