Crud in Angular 10
Crud in Angular 10
We will learn how to build an Angular 10 front-end application that fetches data
from a REST API of products:
• Each product has id, name, description, availability status.
• Users would be able to create, retrieve, update, and delete products.
• Users can search for products by name.
We’ll be building a Angular 10 frontend app for a presumed REST API exporting
the following REST API endpoints:
• POST /api/products create new product
1
• GET /api/products retrieve all products
• GET /api/products/:id retrieve a product by :id
• PUT /api/products/:id update a product by :id
• DELETE /api/products/:id delete a product by :id
• DELETE /api/products delete all products
• GET /api/products?name=[keyword] find all products which name con-
tains the passed keyword.
All of them can work well with this Angular App.
Let’s get started by generating a new Angular 10 project using the CLI. You
need to run the following command:
$ ng new Angular10CRUDExample
The CLI will ask you a couple of questions — If Would you like to add
Angular routing? Type y for Yes and Which stylesheet format would
you like to use? Choose CSS.
Next, we need to generate a bunch of components and a service using the An-
gular CLI as follows:
2
$ ng generate service services/product
$ ng g c components/product-create
$ ng g c components/product-details
$ ng g c components/product-list
We have generated three components product-list, product-details,
product-create and a product service that provides the necessary methods
for sending HTTP requests to the server.
We also have the following artifacts:
– The src/app/app-routing.module.ts module will contain routes for each
component. This file is automatically generated by Angular CLI when you
answered Yes for routing.
– The App component contains the router view and navigation bar.
– The src/app/app.module.ts module declares our Angular components and
import the necessary modules such Angular HttpClient.
We’ll be using the http client and forms in our CRUD application which are
provided in its own modules in Angular so we’ll need to import these modules
— FormsModule and HttpClientModule.
Open src/app/app.module.ts file and import FormsModule, HttpClientModule
as follows:
// [...]
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [ ... ],
imports: [
...
FormsModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
3
Step 4 — Adding Routes for the CRUD Components
We have the components that compose our application UI but we need to link
them with their routes to be able to navigate between them using the Angular
10 Router.
We’ll create three routes:
– /products for the product-list component,
– /products/:id for the product-details component,
– /create for theproduct-create component.
Open the src/app/app-routing.module.ts file and update it as follows:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
4
<li class="nav-item">
<a routerLink="products" class="nav-link">Products</a>
</li>
<li class="nav-item">
<a routerLink="create" class="nav-link">Create</a>
</li>
</div>
</nav>
Next, we need to create a CRUD service that will use Angular 10 HTTPClient
to send HTTP requests to the REST API server.
Open the src/services/product.service.ts file and update it as follows:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProductService {
readAll(): Observable<any> {
return this.httpClient.get(baseURL);
}
read(id): Observable<any> {
return this.httpClient.get(`${baseURL}/${id}`);
}
create(data): Observable<any> {
5
return this.httpClient.post(baseURL, data);
}
delete(id): Observable<any> {
return this.httpClient.delete(`${baseURL}/${id}`);
}
deleteAll(): Observable<any> {
return this.httpClient.delete(baseURL);
}
searchByName(name): Observable<any> {
return this.httpClient.get(`${baseURL}?name=${name}`);
}
}
We have previously generated three components and added them to the router,
let’s now implement the actual functionality of each component.
This component provides a form for submitting a new product with two fields,
name and description. It injects and calls the ProductService.create()
method.
Open the src/components/product-create/product-create.component.ts
file and update it as follows:
import { Component, OnInit } from '@angular/core';
import { ProductService } from 'src/app/services/product.service';
@Component({
selector: 'app-product-create',
templateUrl: './product-create.component.html',
styleUrls: ['./product-create.component.css']
})
export class ProductCreateComponent implements OnInit {
product = {
6
name: '',
description: '',
available: false
};
submitted = false;
ngOnInit(): void {
}
createProduct(): void {
const data = {
name: this.product.name,
description: this.product.description
};
this.productService.create(data)
.subscribe(
response => {
console.log(response);
this.submitted = true;
},
error => {
console.log(error);
});
}
newProduct(): void {
this.submitted = false;
this.product = {
name: '',
description: '',
available: false
};
}
}
Next, open the src/components/product-create/product-create.component.html
file and update it as follows:
<div style="width: 500px; margin: auto;">
<div class="submit-form">
<div *ngIf="!submitted">
<div class="form-group">
<label for="name">Name</label>
7
<input
type="text"
class="form-control"
id="name"
required
[(ngModel)]="product.name"
name="name"
/>
</div>
<div class="form-group">
<label for="description">Description</label>
<input
class="form-control"
id="description"
required
[(ngModel)]="product.description"
name="description"
/>
</div>
<div *ngIf="submitted">
<h3>You successfully created a product!</h3>
<button class="btn btn-success" (click)="newProduct()">New..</button>
</div>
</div>
</div>
Next, let’s implement the product list component, which makes use of the fol-
lowing service methods:
• readAll()
• deleteAll()
• searchByName()
Open the src/components/product-list/product-list.component.ts file
and update it as follows:
import { Component, OnInit } from '@angular/core';
import { ProductService } from 'src/app/services/product.service';
8
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
products: any;
currentProduct = null;
currentIndex = -1;
name = '';
ngOnInit(): void {
this.readProducts();
}
readProducts(): void {
this.productService.readAll()
.subscribe(
products => {
this.products = products;
console.log(products);
},
error => {
console.log(error);
});
}
refresh(): void {
this.readProducts();
this.currentProduct = null;
this.currentIndex = -1;
}
deleteAllProducts(): void {
this.productService.deleteAll()
.subscribe(
response => {
console.log(response);
9
this.readProducts();
},
error => {
console.log(error);
});
}
searchByName(): void {
this.productService.searchByName(this.name)
.subscribe(
products => {
this.products = products;
console.log(products);
},
error => {
console.log(error);
});
}
}
Open the src/components/product-list/product-list.component.html
file and update it as follows:
<div class="list row">
<div class="col-md-8">
<div class="input-group mb-4">
<input
type="text"
class="form-control"
placeholder="Search by name"
[(ngModel)]="name"
/>
<div class="input-group-append">
<button
class="btn btn-outline-secondary"
type="button"
(click)="searchByName()"
>
Search
</button>
</div>
</div>
</div>
<div class="col-md-6">
<h4>Product List</h4>
<ul class="list-group">
<li
10
class="list-group-item"
*ngFor="let product of products; let i = index"
[class.active]="i == currentIndex"
(click)="setCurrentProduct(product, i)"
>
{{ product.name }}
</li>
</ul>
<div *ngIf="!currentProduct">
<br />
<p>Please click on a product</p>
</div>
</div>
</div>
If you click on Edit button of any product, you will be directed to the product
details page with the /products/:id URL.
11
The Product Details Component
Next, let’s implement the product details component of our Angular 10 CRUD
application.
Open the src/components/product-details/product-details.component.ts
file and update it as follows:
import { Component, OnInit } from '@angular/core';
import { ProductService } from 'src/app/services/product.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.css']
})
export class ProductDetailsComponent implements OnInit {
currentproduct = null;
message = '';
constructor(
private productService: ProductService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit(): void {
this.message = '';
this.getProduct(this.route.snapshot.paramMap.get('id'));
}
getProduct(id): void {
this.productService.read(id)
.subscribe(
product => {
this.currentProduct = product;
console.log(product);
},
error => {
console.log(error);
});
}
setAvailableStatus(status): void {
const data = {
name: this.currentProduct.name,
12
description: this.currentProduct.description,
available: status
};
this.productService.update(this.currentProduct.id, data)
.subscribe(
response => {
this.currentProduct.available = status;
console.log(response);
},
error => {
console.log(error);
});
}
updateProduct(): void {
this.productService.update(this.currentProduct.id, this.currentProduct)
.subscribe(
response => {
console.log(response);
this.message = 'The product was updated!';
},
error => {
console.log(error);
});
}
deleteProduct(): void {
this.productService.delete(this.currentProduct.id)
.subscribe(
response => {
console.log(response);
this.router.navigate(['/products']);
},
error => {
console.log(error);
});
}
}
Open the src/components/product-details/product-details.component.html
file and update it as follows:
<div style="width: 500px; margin: auto;">
<div *ngIf="currentProduct" class="edit-form">
<h4>Product</h4>
<form>
13
<div class="form-group">
<label for="title">Name</label>
<input
type="text"
class="form-control"
id="name"
[(ngModel)]="currentProduct.name"
name="name"
/>
</div>
<div class="form-group">
<label for="description">Description</label>
<input
type="text"
class="form-control"
id="description"
[(ngModel)]="currentProduct.description"
name="description"
/>
</div>
<div class="form-group">
<label><strong>Status:</strong></label>
{{ currentProduct.available ? "Available" : "Not available" }}
</div>
</form>
<button
class="badge badge-primary mr-2"
*ngIf="currentProduct.available"
(click)="setAvailableStatus(false)"
>
Set Not Available
</button>
<button
*ngIf="!currentProduct.available"
class="badge badge-primary mr-2"
(click)="setAvailableStatus(true)"
>
Set Available
</button>
14
<button
type="submit"
class="badge badge-success"
(click)="updateProduct()"
>
Update
</button>
<p>{{ message }}</p>
</div>
<div *ngIf="!currentProduct">
<br />
<p>This product is not accessible</p>
</div>
</div>
Head back to your command-line interface, make sure your are navigated at the
root of your project’s directory and run the following command to start a live
development server in your local machine:
$ cd Angular10CRUDExample
$ ng serve
Go to your web browser and navigate to the http://localhost:4200/ address
to start testing your app.
Conclusion
In this tutorial, we’ve built an Angular 10 CRUD application for a Web REST
API. Make sure to visit us at Techiediaries for more indepth tutorials about
Angular and modern web development.
By Techiediaries.com
15