In this tutorial, I will show you how to build an Angular 8 CRUD Application to consume Web APIs, display, modify & search data.
Newer versions:
– Angular 10 CRUD example with Web API
– Angular 11 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
More Practice:
– Angular 8 JWT Authentication with HttpInterceptor and Router
– Angular 8 Multiple Files upload example
– Angular 8 + Spring Boot: File upload example
Fullstack CRUD Application:
– Angular 8 + Node.js Express + MySQL example
– Angular 8 + Node.js Express + PostgreSQL example
– Angular 8 + Node.js Express + MongoDB example
– Angular 8 + Spring Boot + MySQL example
– Angular 8 + Spring Boot + PostgreSQL example
– Angular 8 + Spring Boot + MongoDB example
– Angular 8 + Django example
– Angular 8 + Django + MySQL example
– Angular 8 + Django + PostgreSQL example
– Angular 8 + Django + MongoDB example
Serverless with Firebase:
– Angular 8 Firebase CRUD Realtime DB | AngularFireDatabase
Contents
- Overview of Angular 8 CRUD Application
- Web API
- Angular App Component Diagram
- Setup Angular 8 Project
- Project Structure
- Set up App Module
- Define Routes for Angular AppRoutingModule
- Add Navbar and Router View to Angular CRUD App
- Create Data Service
- Create Angular Components
- Run the Angular App
- Source Code
- Conclusion
- Further Reading
Overview of Angular 8 CRUD Application
We will build an Angular 8 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 a Tutorial:
– Retrieve all Tutorials:
– Click on Edit button to update a Tutorial:
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
– Search Tutorials by title:
Web API
The introduction above is for Angular Client with assumption that we have a Server exporting REST APIs:
Methods | Urls | Actions |
---|---|---|
POST | /api/tutorials | create new Tutorial |
GET | /api/tutorials | retrieve all Tutorials |
GET | /api/tutorials/:id | retrieve a Tutorial by :id |
PUT | /api/tutorials/:id | update a Tutorial by :id |
DELETE | /api/tutorials/:id | delete a Tutorial by :id |
DELETE | /api/tutorials | delete 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:
– Express, Sequelize & MySQL
– Express, Sequelize & PostgreSQL
– Express, Sequelize & SQL Server
– Express & MongoDb
– Spring Boot & MySQL
– Spring Boot & PostgreSQL
– Spring Boot & MongoDB
– Spring Boot & SQL Server
– Spring Boot & H2
– Spring Boot & Cassandra
– Spring Boot & Oracle
– Python/Django & MySQL
– Python/Django & PostgreSQL
– Python/Django & MongoDB
All of them can work well with this Angular App.
Angular App Component Diagram
– 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 8 Project
Let’s open cmd and use Angular CLI to create a new Angular Project as following command:
ng new Angular8ClientCrud
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
We also need to generate some Components and Services:
ng g s services/tutorial
ng g c components/add-tutorial
ng g c components/tutorial-details
ng g c components/tutorials-list
Now you can see that our project directory structure looks like this.
Project Structure
Let me explain it briefly.
– 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 { }
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>
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';
const baseUrl = 'http://localhost:8080/api/tutorials';
@Injectable({
providedIn: 'root'
})
export class TutorialService {
constructor(private http: HttpClient) { }
getAll() {
return this.http.get(baseUrl);
}
get(id) {
return this.http.get(`${baseUrl}/${id}`);
}
create(data) {
return this.http.post(baseUrl, data);
}
update(id, data) {
return this.http.put(`${baseUrl}/${id}`, data);
}
delete(id) {
return this.http.delete(`${baseUrl}/${id}`);
}
deleteAll() {
return this.http.delete(baseUrl);
}
findByTitle(title) {
return this.http.get(`${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 { 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 = {
title: '',
description: '',
published: false
};
submitted = false;
constructor(private tutorialService: TutorialService) { }
ngOnInit() {
}
saveTutorial() {
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() {
this.submitted = false;
this.tutorial = {
title: '',
description: '',
published: false
};
}
}
components/add-tutorial/add-tutorial.component.html
<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>You submitted successfully!</h4>
<button class="btn btn-success" (click)="newTutorial()">Add</button>
</div>
</div>
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 { 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: any;
currentTutorial = null;
currentIndex = -1;
title = '';
constructor(private tutorialService: TutorialService) { }
ngOnInit() {
this.retrieveTutorials();
}
retrieveTutorials() {
this.tutorialService.getAll()
.subscribe(
data => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
refreshList() {
this.retrieveTutorials();
this.currentTutorial = null;
this.currentIndex = -1;
}
setActiveTutorial(tutorial, index) {
this.currentTutorial = tutorial;
this.currentIndex = index;
}
removeAllTutorials() {
this.tutorialService.deleteAll()
.subscribe(
response => {
console.log(response);
this.retrieveTutorials();
},
error => {
console.log(error);
});
}
searchTitle() {
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" href="/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
.
You can add Pagination to this Component, just follow instruction in the post:
Angular 8 Pagination with ngx-pagination example
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';
@Component({
selector: 'app-tutorial-details',
templateUrl: './tutorial-details.component.html',
styleUrls: ['./tutorial-details.component.css']
})
export class TutorialDetailsComponent implements OnInit {
currentTutorial = null;
message = '';
constructor(
private tutorialService: TutorialService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit() {
this.message = '';
this.getTutorial(this.route.snapshot.paramMap.get('id'));
}
getTutorial(id) {
this.tutorialService.get(id)
.subscribe(
data => {
this.currentTutorial = data;
console.log(data);
},
error => {
console.log(error);
});
}
updatePublished(status) {
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);
},
error => {
console.log(error);
});
}
updateTutorial() {
this.tutorialService.update(this.currentTutorial.id, this.currentTutorial)
.subscribe(
response => {
console.log(response);
this.message = 'The tutorial was updated successfully!';
},
error => {
console.log(error);
});
}
deleteTutorial() {
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 *ngIf="currentTutorial" 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" (click)="updateTutorial()">
Update
</button>
<p>{{ message }}</p>
</div>
<div *ngIf="!currentTutorial">
<br />
<p>Cannot access this Tutorial...</p>
</div>
Run the Angular 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:
– Express, Sequelize & MySQL
– Express, Sequelize & PostgreSQL
– Express, Sequelize & SQL Server
– Express & MongoDb
– Spring Boot & MySQL
– Spring Boot & PostgreSQL
– Spring Boot & MongoDB
– Spring Boot & SQL Server
– Spring Boot & H2
– Spring Boot & Cassandra
– Spring Boot & Oracle
– Python/Django & MySQL
– Python/Django & PostgreSQL
– Python/Django & MongoDB
It configures CORS for port 8081
, so you have to run command: ng serve --port 8081
instead.
This is the demo video with brief instruction:
Conclusion
Today we’ve built an Angular 8 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.
You can find newer versions of this Angular App at the posts:
– Angular 10 CRUD Application example with Web API
– Angular 11 CRUD Application example with Web API
– Angular 12 CRUD Application example with Web API
– Angular 13 CRUD Application example with Web API
Or you can add Pagination Component:
Angular 8 Pagination with ngx-pagination example
Happy learning, see you again!
Further Reading
Fullstack CRUD Application:
- Angular 8 + Node.js Express + MySQL example
- Angular 8 + Node.js Express + PostgreSQL example
- Angular 8 + Node.js Express + MongoDB example
- Angular 8 + Spring Boot + MySQL example
- Angular 8 + Spring Boot + PostgreSQL example
- Angular 8 + Spring Boot + MongoDB example
- Angular 8 + Django example
- Angular 8 + Django + MySQL example
- Angular 8 + Django + PostgreSQL example
- Angular 8 + Django + MongoDB example
Integration:
– Integrate Angular 8 with Node.js Restful Services
– Integrate Angular with Spring Boot Rest API
Serverless with Firebase:
– Angular 8 Firebase CRUD Realtime DB | AngularFireDatabase
Source Code
You can find the complete source code for this tutorial on Github.
Hello, why is the currentIndex -1?
Hi, it shows that there is no selected tutorial.
Hi Sir,
I am able to run this code successfully in Windows machine. When i tried to run the code in mac machine data not showing in UI. Can you please help on this issue.
Thank you my friend 🙂
I have follwed all the steps but my “submit” button is not functioning…please help
Hi, you should run one of the backend servers I mention in the tutorials.
hi thanks for the article, but what if i want to do it with out an API but hard code the item directly how can i do that ?
The log gives:
Access to XMLHttpRequest at ‘http://localhost:8080/api/tutorials’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
Hi, you should run Angular client with command:
ng serve --port 8081
.Hello sir, thank you for your detailed tutorial. I got all the code(back+front) from github and ran both. They ran fine without an error, but I cannot add any tutorial(clicking SUBMIT gives nothing). Can you please help? Thank you.
hello, sir, thanks so much for your tutorial, can I ask you a question? i got a problem in tutorial-list.ts, my Angular shows there is no existing tutorials, i might change tutorials to tutorial in this.tutorials.data. meanwhile, current.Index still has the same issue which can not find in tutorial-list.component.ts. cheers!
i have worked them out, thanks!! i made a mistake. BTW,this is working, but tutorials list can not be shown on the page, and once i add tutorial, there is still no response on the page. Sorry about my question, i am new to Angular
Hi, is it possible to handle all crud operation in one single component
Yes, you can do it by import AddTutorial and TutorialDetails as child components into TutorialsList component.
Thank you for this tutorial. I’m having issues using this with your Node.js Rest APIs example with Express, Sequelize & MySQL. I’m getting ERR_NAME_NOT_RESOLVED errors, for example “POST http://localhost8080/api/tutorials net::ERR_NAME_NOT_RESOLVED” when I try to add a tutorial, or “GET http://localhost8080/api/tutorials net::ERR_NAME_NOT_RESOLVED” when loading the home page.
My Add page is accessible, but don’t show the form.
Thanks for sharing it.
You have explained every detail. When it comes to building a Crud app with Angular, there are essentials that Angular web developer practices. The first thing to do is to deal with a mountain of data. This data then that lives on the server is dealt with using HTTP operations. In a real app, the data is stored on the server and received via the API.
Hi, this is Alok bharti fron India i am facing some error all are run perfect but backend data is not on web page.
Hi, you should use one of the backend servers that I provided in the tutorials 🙂
Thanks for tour effort to make this long Angular CRUD tutorial.
Hi!
i’m facing a probleme with tutorials-list.component.ts when i write this.retrieveTutorials();
– error TS2339: Property ‘retrieveTutorial’ does not exist ;
Hi,
retrieveTutorial
should have ‘s’ at the end 🙂How do you run this frontend with the backend api of Mongoose, Express and NodeJS that youve mentioned in another post? theyre in two separate folders names backend and frontend.
Yeah, the backend is in another post.
You can visit this post that covers the idea of inplementing the system.
Hi there, thanks for this tutorial!
However, I’ve encountered an issue when i tried to search a tutorial i’ve just created, can you please help me?
Ps: I’m working on the github version of this app
Hi, please tell me your problem. What is the issue? 🙂
i did every step correctly, but there is an error with every code that contains “[(ngModel)]=”
it says “Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’.ng(0)”
what might be the problem?
Hi, did you import
FormsModule
in app.module.ts?Hi, I’m not the OP, but same problem.
Yes, I did import FormsModule in app.module.ts. Still have OP error.
If it helps, VS Code warns “‘FormsModule’ is declared but its value is never read. ts(6133)” HttpClientModule has the same warning, in case that matters.
Thanks for all your work on these. I’m just starting to learn JS/TS/Angular, and your tutorials have been great so far.
Hi, you should use them in the
imports
(the tutorial said it clearly):Thanks for the quick reply.
Of course, you’re right. The tutorial did say it clearly. I just missed it, even after going back and re-reading. A lot of detail and structure for the two-volts between my ears.
Great tutorial, and again, thank you.
Had same error, in order to fix it, I had to add the new components to the declarations
Ah yeah, but this will be automatically added with command:
ng g c YourComponent
🙂Hello, how are you? Sorry for my bad English. I write to you from Argentina. Everything worked perfect, however, I load the pages without styles, I can not attach a screen print, but it is only forms and titles without styles. With the development tool I don’t see any error in loading any resources. Could you help me?
From already thank you very much,
Best regards,
Hi, you can pull source code from github, it’s bootstrap imported in index.html file.
You can easily install bootstrap in angular 8.
Step by step is very easy.
You can run this in your project root terminal
ng add @ng-bootstrap/ng-bootstrap