Angular 11 CRUD Application example with Web API - BezKoder (2024)

In this tutorial, I will show you how to build an Angular 11 CRUD Application to consume Web APIs, display, modify & search data.

Other versions:
Angular 8 CRUD example with Web API
Angular 10 CRUD example with Web API
Angular 12 CRUD example with Web API
Angular 13 CRUD example with Web API
Angular 14 CRUD example with Web API
Angular 15 CRUD example with Web API
Angular 16 CRUD example with Web API
Angular 17 CRUD example with Web API

Fullstack CRUD Application:
Angular + Node.js Express + MySQL example
Angular + Node.js Express + PostgreSQL example
Angular + Node.js Express + MongoDB example
Angular + Spring Boot + MySQL example
Angular + Spring Boot + PostgreSQL example
Angular + Spring Boot + MongoDB example
Angular + Django example
Angular + Django + MySQL example
Angular + Django + PostgreSQL example
Angular + Django + MongoDB example

Authentication: Angular 11 JWT Authentication example with Web Api

More Practice:
Angular 11 Form Validation example (Reactive Forms)
Angular 11 File upload example with Progress bar
Angular 11 Multiple Files upload example with Progress Bar

Contents

  • Overview of Angular 11 CRUD Application
  • Web API
  • Angular App Component Diagram
  • Setup Angular 11 Project
  • Project Structure
  • Set up App Module
  • Define Routes for Angular AppRoutingModule
  • Add Navbar and Router View to Angular CRUD App
  • Define Model Class
  • Create Data Service
  • Create Angular Components
    • Add new Item Component
    • List of items Component
    • Item details Component
  • Run the Angular 11 CRUD App
  • Source Code
  • Conclusion
  • Further Reading

Overview of Angular 11 CRUD Application

We will build an Angular 11 front-end Tutorial Application in that:

  • Each Tutorial has id, title, description, published status.
  • We can create, retrieve, update, delete Tutorials.
  • There is a Search bar for finding Tutorials by title.

Here are screenshots of our Angular CRUD Application.

– Create an object:

Angular 11 CRUD Application example with Web API - BezKoder (1)

– Retrieve all objects:

Angular 11 CRUD Application example with Web API - BezKoder (2)

– Click on Edit button to update an object:

Angular 11 CRUD Application example with Web API - BezKoder (3)

On this Page, you can:

  • change status to Published using Publish button
  • delete the Tutorial using Delete button
  • update the Tutorial details with Update button

Angular 11 CRUD Application example with Web API - BezKoder (4)

– Search Tutorials by title:

Angular 11 CRUD Application example with Web API - BezKoder (5)

You can implement Form Validation, please visit:
Angular 11 Form Validation example (Reactive Forms)

Web API

The introduction above is for Angular Client with assumption that we have a Server exporting REST APIs:

MethodsUrlsActions
POST/api/tutorialscreate new Tutorial
GET/api/tutorialsretrieve all Tutorials
GET/api/tutorials/:idretrieve a Tutorial by :id
PUT/api/tutorials/:idupdate a Tutorial by :id
DELETE/api/tutorials/:iddelete a Tutorial by :id
DELETE/api/tutorialsdelete all Tutorials
GET/api/tutorials?title=[keyword]find all Tutorials which title contains keyword

You can find step by step to build a Server like this in one of these posts:













All of them can work well with this Angular App.

Angular 11 CRUD App Component Diagram

Angular 11 CRUD Application example with Web API - BezKoder (6)

– The App component is a container with router-outlet. It has navbar that links to routes paths via routerLink.

TutorialsList component gets and displays Tutorials.
Tutorial component has form for editing Tutorial’s details based on :id.
AddTutorial component has form for submission new Tutorial.

– These Components call TutorialService methods which use Angular HTTPClient to make HTTP requests and receive responses.

Setup Angular 11 Project

Let’s open cmd and use Angular CLI to create a new Angular Project as following command:

ng new Angular11Crud? Would you like to add Angular routing? Yes? Which stylesheet format would you like to use? CSS

Angular 11 CRUD Application example with Web API - BezKoder (7)

We also need to generate some Components and Services:

ng g s services/tutorialng g c components/add-tutorialng g c components/tutorial-detailsng g c components/tutorials-listng g class models/tutorial --type=model

Now you can see that our project directory structure looks like this.

Project Structure

Angular 11 CRUD Application example with Web API - BezKoder (8)

Let me explain it briefly.

tutorial.model.ts exports the main class model: Tutorial.
– There are 3 components: tutorials-list, tutorial-details, add-tutorial.
tutorial.service has methods for sending HTTP requests to the Apis.
app-routing.module.ts defines routes for each component.
app component contains router view and navigation bar.
app.module.ts declares Angular components and import necessary modules.

Set up App Module

Open app.module.ts and import FormsModule, HttpClientModule:

...import { FormsModule } from '@angular/forms';import { HttpClientModule } from '@angular/common/http';@NgModule({ declarations: [ ... ], imports: [ ... FormsModule, HttpClientModule ], providers: [], bootstrap: [AppComponent]})export class AppModule { }

Define Routes for Angular AppRoutingModule

There are 3 main routes:
/tutorials for tutorials-list component
/tutorials/:id for tutorial-details component
/add for add-tutorial component

app-routing.module.ts

import { NgModule } from '@angular/core';import { Routes, RouterModule } from '@angular/router';import { TutorialsListComponent } from './components/tutorials-list/tutorials-list.component';import { TutorialDetailsComponent } from './components/tutorial-details/tutorial-details.component';import { AddTutorialComponent } from './components/add-tutorial/add-tutorial.component';const routes: Routes = [ { path: '', redirectTo: 'tutorials', pathMatch: 'full' }, { path: 'tutorials', component: TutorialsListComponent }, { path: 'tutorials/:id', component: TutorialDetailsComponent }, { path: 'add', component: AddTutorialComponent }];@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule]})export class AppRoutingModule { }

Add Navbar and Router View to Angular 11 CRUD App

Let’s open src/app.component.html, this App component is the root container for our application, it will contain a nav element.

<div> <nav class="navbar navbar-expand navbar-dark bg-dark"> <a href="#" class="navbar-brand">bezKoder</a> <div class="navbar-nav mr-auto"> <li class="nav-item"> <a routerLink="tutorials" class="nav-link">Tutorials</a> </li> <li class="nav-item"> <a routerLink="add" class="nav-link">Add</a> </li> </div> </nav> <div class="container mt-3"> <router-outlet></router-outlet> </div></div>

Define Model Class

Our main model class Tutorial will be exported in tutorial.model.ts with 4 fields:

  • id
  • title
  • description
  • published

models/tutorial.model.ts

export class Tutorial { id?: any; title?: string; description?: string; published?: boolean;}

Create Data Service

This service will use Angular HTTPClient to send HTTP requests.
You can see that its functions includes CRUD operations and finder method.

services/tutorial.service.ts

import { Injectable } from '@angular/core';import { HttpClient } from '@angular/common/http';import { Observable } from 'rxjs';import { Tutorial } from '../models/tutorial.model';const baseUrl = 'http://localhost:8080/api/tutorials';@Injectable({ providedIn: 'root'})export class TutorialService { constructor(private http: HttpClient) { } getAll(): Observable<Tutorial[]> { return this.http.get<Tutorial[]>(baseUrl); } get(id: any): Observable<Tutorial> { return this.http.get(`${baseUrl}/${id}`); } create(data: any): Observable<any> { return this.http.post(baseUrl, data); } update(id: any, data: any): Observable<any> { return this.http.put(`${baseUrl}/${id}`, data); } delete(id: any): Observable<any> { return this.http.delete(`${baseUrl}/${id}`); } deleteAll(): Observable<any> { return this.http.delete(baseUrl); } findByTitle(title: any): Observable<Tutorial[]> { return this.http.get<Tutorial[]>(`${baseUrl}?title=${title}`); }}

Create Angular Components

As you’ve known before, there are 3 components corresponding to 3 routes defined in AppRoutingModule.

Add new Item Component

This component has a Form to submit new Tutorial with 2 fields: title & description. It calls TutorialService.create() method.

components/add-tutorial/add-tutorial.component.ts

import { Component, OnInit } from '@angular/core';import { Tutorial } from 'src/app/models/tutorial.model';import { TutorialService } from 'src/app/services/tutorial.service';@Component({ selector: 'app-add-tutorial', templateUrl: './add-tutorial.component.html', styleUrls: ['./add-tutorial.component.css']})export class AddTutorialComponent implements OnInit { tutorial: Tutorial = { title: '', description: '', published: false }; submitted = false; constructor(private tutorialService: TutorialService) { } ngOnInit(): void { } saveTutorial(): void { const data = { title: this.tutorial.title, description: this.tutorial.description }; this.tutorialService.create(data) .subscribe( response => { console.log(response); this.submitted = true; }, error => { console.log(error); }); } newTutorial(): void { this.submitted = false; this.tutorial = { title: '', description: '', published: false }; }}

components/add-tutorial/add-tutorial.component.html

<div> <div class="submit-form"> <div *ngIf="!submitted"> <div class="form-group"> <label for="title">Title</label> <input type="text" class="form-control" id="title" required [(ngModel)]="tutorial.title" name="title" /> </div> <div class="form-group"> <label for="description">Description</label> <input class="form-control" id="description" required [(ngModel)]="tutorial.description" name="description" /> </div> <button (click)="saveTutorial()" class="btn btn-success">Submit</button> </div> <div *ngIf="submitted"> <h4>Tutorial was submitted successfully!</h4> <button class="btn btn-success" (click)="newTutorial()">Add</button> </div> </div></div>

components/add-tutorial/add-tutorial.component.css

.submit-form { max-width: 400px; margin: auto;}

List of items Component

This component calls 3 TutorialService methods:

  • getAll()
  • deleteAll()
  • findByTitle()

components/tutorials-list/tutorials-list.component.ts

import { Component, OnInit } from '@angular/core';import { Tutorial } from 'src/app/models/tutorial.model';import { TutorialService } from 'src/app/services/tutorial.service';@Component({ selector: 'app-tutorials-list', templateUrl: './tutorials-list.component.html', styleUrls: ['./tutorials-list.component.css']})export class TutorialsListComponent implements OnInit { tutorials?: Tutorial[]; currentTutorial?: Tutorial; currentIndex = -1; title = ''; constructor(private tutorialService: TutorialService) { } ngOnInit(): void { this.retrieveTutorials(); } retrieveTutorials(): void { this.tutorialService.getAll() .subscribe( data => { this.tutorials = data; console.log(data); }, error => { console.log(error); }); } refreshList(): void { this.retrieveTutorials(); this.currentTutorial = undefined; this.currentIndex = -1; } setActiveTutorial(tutorial: Tutorial, index: number): void { this.currentTutorial = tutorial; this.currentIndex = index; } removeAllTutorials(): void { this.tutorialService.deleteAll() .subscribe( response => { console.log(response); this.refreshList(); }, error => { console.log(error); }); } searchTitle(): void { this.tutorialService.findByTitle(this.title) .subscribe( data => { this.tutorials = data; console.log(data); }, error => { console.log(error); }); }}

components/tutorials-list/tutorials-list.component.html

<div class="list row"> <div class="col-md-8"> <div class="input-group mb-3"> <input type="text" class="form-control" placeholder="Search by title" [(ngModel)]="title" /> <div class="input-group-append"> <button class="btn btn-outline-secondary" type="button" (click)="searchTitle()" > Search </button> </div> </div> </div> <div class="col-md-6"> <h4>Tutorials List</h4> <ul class="list-group"> <li class="list-group-item" *ngFor="let tutorial of tutorials; let i = index" [class.active]="i == currentIndex" (click)="setActiveTutorial(tutorial, i)" > {{ tutorial.title }} </li> </ul> <button class="m-3 btn btn-sm btn-danger" (click)="removeAllTutorials()"> Remove All </button> </div> <div class="col-md-6"> <div *ngIf="currentTutorial"> <h4>Tutorial</h4> <div> <label><strong>Title:</strong></label> {{ currentTutorial.title }} </div> <div> <label><strong>Description:</strong></label> {{ currentTutorial.description }} </div> <div> <label><strong>Status:</strong></label> {{ currentTutorial.published ? "Published" : "Pending" }} </div> <a class="badge badge-warning" routerLink="/tutorials/{{ currentTutorial.id }}"> Edit </a> </div> <div *ngIf="!currentTutorial"> <br /> <p>Please click on a Tutorial...</p> </div> </div></div>

If you click on Edit button of any Tutorial, You will be directed to Tutorial page with url: /tutorials/:id.

components/tutorials-list/tutorials-list.component.css

.list { text-align: left; max-width: 750px; margin: auto;}

You can add Pagination to this Component, just follow instruction in the post:
Angular 11 Pagination example with ngx-pagination

Item details Component

For getting data & update, delete the Tutorial, this component will use 3 TutorialService methods:

  • get()
  • update()
  • delete()

components/tutorial-details/tutorial-details.component.ts

import { Component, OnInit } from '@angular/core';import { TutorialService } from 'src/app/services/tutorial.service';import { ActivatedRoute, Router } from '@angular/router';import { Tutorial } from 'src/app/models/tutorial.model';@Component({ selector: 'app-tutorial-details', templateUrl: './tutorial-details.component.html', styleUrls: ['./tutorial-details.component.css']})export class TutorialDetailsComponent implements OnInit { currentTutorial: Tutorial = { title: '', description: '', published: false }; message = ''; constructor( private tutorialService: TutorialService, private route: ActivatedRoute, private router: Router) { } ngOnInit(): void { this.message = ''; this.getTutorial(this.route.snapshot.params.id); } getTutorial(id: string): void { this.tutorialService.get(id) .subscribe( data => { this.currentTutorial = data; console.log(data); }, error => { console.log(error); }); } updatePublished(status: boolean): void { const data = { title: this.currentTutorial.title, description: this.currentTutorial.description, published: status }; this.tutorialService.update(this.currentTutorial.id, data) .subscribe( response => { this.currentTutorial.published = status; console.log(response); this.message = response.message; }, error => { console.log(error); }); } updateTutorial(): void { this.tutorialService.update(this.currentTutorial.id, this.currentTutorial) .subscribe( response => { console.log(response); this.message = response.message; }, error => { console.log(error); }); } deleteTutorial(): void { this.tutorialService.delete(this.currentTutorial.id) .subscribe( response => { console.log(response); this.router.navigate(['/tutorials']); }, error => { console.log(error); }); }}

components/tutorial-details/tutorial-details.component.html

<div> <div *ngIf="currentTutorial.id" class="edit-form"> <h4>Tutorial</h4> <form> <div class="form-group"> <label for="title">Title</label> <input type="text" class="form-control" id="title" [(ngModel)]="currentTutorial.title" name="title" /> </div> <div class="form-group"> <label for="description">Description</label> <input type="text" class="form-control" id="description" [(ngModel)]="currentTutorial.description" name="description" /> </div> <div class="form-group"> <label><strong>Status:</strong></label> {{ currentTutorial.published ? "Published" : "Pending" }} </div> </form> <button class="badge badge-primary mr-2" *ngIf="currentTutorial.published" (click)="updatePublished(false)" > UnPublish </button> <button *ngIf="!currentTutorial.published" class="badge badge-primary mr-2" (click)="updatePublished(true)" > Publish </button> <button class="badge badge-danger mr-2" (click)="deleteTutorial()"> Delete </button> <button type="submit" class="badge badge-success mb-2" (click)="updateTutorial()" > Update </button> <p>{{ message }}</p> </div> <div *ngIf="!currentTutorial.id"> <br /> <p>Cannot access this Tutorial...</p> </div></div>

components/tutorial-details/tutorial-details.component.css

.edit-form { max-width: 400px; margin: auto;}

Run the Angular 11 CRUD App

You can run this App with command: ng serve.

If you use this front-end app for one of these back-end Rest APIs:













It configures CORS for port 8081, so you have to run command: ng serve --port 8081 instead.

Conclusion

Today we’ve built an Angular 11 CRUD Application successfully working with Web API. Now we can, display, modify, delete or search data in a clean way. I hope you apply it in your project at ease.

For adding Form Validation, please visit:
Angular 11 Form Validation example (Reactive Forms)

You can also find how to implement Authentication with the post:
Angular 11 JWT Authentication example with Web Api

Or you can add Pagination Component:
Angular 11 Pagination example with ngx-pagination

Angular 11 CRUD Application example with Web API - BezKoder (9)

Or implement File Upload Component:
Angular 11 File upload example with Progress bar

Happy learning, see you again!

Further Reading

Serverless with Firebase:
Angular 11 Firebase CRUD Realtime DB | AngularFireDatabase
Angular 11 Firestore CRUD example | AngularFireStore
Angular 11 File Upload Firebase Storage: Display/Delete Files example

Integration:
How to Integrate Angular with Node.js Rest API
How to Integrate Angular 11 with Spring Boot Rest API

Source Code

You can find the complete source code for this tutorial on Github.

Angular 11 CRUD Application example with Web API - BezKoder (2024)

References

Top Articles
Latest Posts
Article information

Author: Gov. Deandrea McKenzie

Last Updated:

Views: 6071

Rating: 4.6 / 5 (46 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Gov. Deandrea McKenzie

Birthday: 2001-01-17

Address: Suite 769 2454 Marsha Coves, Debbieton, MS 95002

Phone: +813077629322

Job: Real-Estate Executive

Hobby: Archery, Metal detecting, Kitesurfing, Genealogy, Kitesurfing, Calligraphy, Roller skating

Introduction: My name is Gov. Deandrea McKenzie, I am a spotless, clean, glamorous, sparkling, adventurous, nice, brainy person who loves writing and wants to share my knowledge and understanding with you.