Angular 8 App Crud Operation Tutorial From Scratch

Befor get started with angular 8 crud operation. You must have installed Angular 8 project. If you don’t know how to setup Angular 8 project follow ‘How to Install Angular 8‘ article to setup Angular 8 project.

So let’s get start:

Create Angular 8 Component

What is component?
Components are a logical piece of code for Angular JS application. We will create three component.

Type the following command to generate Angular 8 Components. We will perform create, read, update operations. So we will create three components.

To create it:

ng g component todo
ng g component todoAdd
ng g component todoEdit

Open src/app/app.module.ts you will see all the three components imported and declared in declarations section by Angular 8 itself.

Create Angular 8 Routing

Now We need to create route for the above created component. So when you navigate the route you will be see the html of your component.

To create new route open the “app-routing.module.ts” file under the “your project directory > src > app”.

Import all three above created component to the routing module. Add the below line in the top of the “app-routing.module.ts” file.

import { TodoComponent } from './todo/todo.component';
import { TodoAddComponent } from './todo-add/todo-add.component';
import { TodoEditComponent } from './todo-edit/todo-edit.component';

You will see the route variable. Changed with this

const routes: Routes = [
  {
    path: '',
    component: TodoComponent,
    data: { title: 'List of todos' }
  },
  {
    path: 'todo/add',
    component: TodoAddComponent,
    data: { title: 'Add todo' }
  },
  {
    path: 'todo/edit/:id',
    component: TodoEditComponent,
    data: { title: 'Edit todo' }
  },
];

Install bootstrap 4 CSS Framwork

Next, install the Bootstrap 4 CSS Framework using the following command.

npm install bootstrap --save

Now, add it inside the angular.json file.

"styles": [
   "src/styles.css",
   "./node_modules/bootstrap/dist/css/bootstrap.min.css"
 ]

So, now we can use the Bootstrap 4 classes in our project.

Configure the Angular 8 Form Validation

We will use ReactiveFormsModule for Angular 8 Form Validation.
Now, import the ReactiveFormsModule inside the app.module.ts file.

import { ReactiveFormsModule } from '@angular/forms';

imports: [
    ReactiveFormsModule
],

Create Todo Class

Now, we create a class like model class.

To create Todo class run the below command

ng g class todo

Now, write all properties of the Todo class related to an todo that matches with the database. Open the todo.ts file and put the below code.

export class Todo {
    id: number;
    title: string;
    updated_at: Date;
}

Modify Angular 8 entry page

Open src/app/app.component.html and modify this HTML page to fit the CRUD page. Replace with the following html

<router-outlet></router-outlet>

Modify todo list component

Open src/app/todo.component.html and put the below html

<div class="container mt-5">
  <h2>Todos
    <a class="float-right" [routerLink]="['/todo/add']">
      <button type="button" class="btn btn-primary">Add</button>
    </a>
  </h2>
  <table class="table table-bordered mt-5">
    <thead>
      <tr>
        <th>ID</th>
        <th>Title</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
        <tr *ngFor="let item of data; let i = index;">
            <td width="20">{{item.id}}</td>
            <td>{{item.title}}</td>
            <td width="250">                
                <button type="button" class="btn btn-danger mr-1" (click)="deleteTodo(item.id, i)">Delete</button>
                <a [routerLink]="['/todo/edit/', item.id]">
                  <button type="button" class="btn btn-primary">Edit</button>
                </a>
            </td>
          </tr>
    </tbody>
  </table>
</div>

Open src/app/todo.component.ts and put the below code

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../api.service';
import { Todo } from '../todo';

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

  data: Todo[] = [];

  constructor(private api: ApiService) { }
  

  ngOnInit() {
    this.api.getTodos()
      .subscribe(res => {
        this.data = res;
      }, err => {
        console.log(err);
      });
  }

  deleteTodo(id, index) {
    this.api.deleteTodo(id)
      .subscribe(res => {    
          this.data.splice(index,1);
        }, (err) => {
          console.log(err);
        }
      );
  }
}

Modify todo add component

Open src/app/todo-add.component.html and put the below html

<div class="row mt-5">
  <div class="col-md-6 mx-auto">
      <h2 class="text-center">Add Todo</h2>
      <div class="card mt-3">
          <div class="card-body">
            <form [formGroup]="todoForm" (ngSubmit)="addTodo()">
              <div class="form-group">
                <label class="col-md-4">Title </label>
                <input type="text" class="form-control" formControlName="title" />
              </div>
              <div class="form-group">
                <button type="submit" class="btn btn-primary col-md-4" [disabled]="todoForm.invalid">Add</button>
                <a [routerLink]="['/']">
                  <button type="submit" class="btn btn-primary col-md-4 ml-1">Back</button>
                </a>
              </div>
            </form>
          </div>
      </div>
  </div>
</div>

Open src/app/todo-add.component.ts and put the below code

import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import { ApiService } from '../api.service';
import {Router} from "@angular/router";

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

export class TodoAddComponent implements OnInit {
  
  todoForm: FormGroup;
  constructor(private formBuilder: FormBuilder, private router: Router, private api: ApiService) { }


  ngOnInit() {
    this.todoForm = this.formBuilder.group({
      title: ['', Validators.compose([Validators.required])],
    });
  }

  addTodo() {
    const payload = {
      title: this.todoForm.controls.title.value,
    };

    this.api.addTodo(payload)
      .subscribe(res => {
          let id = res['_id'];
          this.router.navigate(['/']);
        }, (err) => {
          console.log(err);
        });
  }
}

Modify todo edit component

Open src/app/todo-edit.component.html and put the below html

<div class="row mt-5">
  <div class="col-md-6 mx-auto">
      <h2 class="text-center">Update Todo</h2>
      <div class="card mt-3">
          <div class="card-body">
            <form [formGroup]="todoForm" (ngSubmit)="updateTodo(todoForm.value)">
              <div class="form-group">
                <label class="col-md-4">Title </label>
                <input type="text" class="form-control" formControlName="title" />
              </div>
              <div class="form-group">
                <button type="submit" class="btn btn-primary col-md-4" [disabled]="todoForm.invalid">Update</button>
                <a [routerLink]="['/']">
                  <button type="submit" class="btn btn-primary col-md-4 ml-1">Back</button>
                </a>
              </div>
            </form>
          </div>
      </div>
  </div>
</div>

Open src/app/todo-edit.component.ts and put the below code

import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators, NgForm} from "@angular/forms";
import { ApiService } from '../api.service';
import { ActivatedRoute, Router } from '@angular/router';

import { Todo } from '../todo';

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

  todoForm: FormGroup;
  id:number= null;

  constructor(
    private formBuilder: FormBuilder, 
    private activeAouter: ActivatedRoute, 
    private router: Router, 
    private api: ApiService
  ) { }

  ngOnInit() {
    
    this.getDetail(this.activeAouter.snapshot.params['id']);

    this.todoForm = this.formBuilder.group({
      title: ['', Validators.compose([Validators.required])],
    });
  }

  getDetail(id) {
    this.api.getTodo(id)
      .subscribe(data => {
        this.id = data.id;
        this.todoForm.setValue({
          title: data.title
        });
        console.log(data);
      });
  }
  updateTodo(form:NgForm) {

    this.api.updateTodo(this.id, form)
      .subscribe(res => {
          this.router.navigate(['/']);
        }, (err) => {
          console.log(err);
        }
      );
    
  }

}

Configure the HttpClientModule

We need HttpClientModule to access RESTful API. So before creating a service, first, Open src/app/app.module.ts then add this import.

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

Add HttpClientModule to imports array under @NgModule

imports: [
    HttpClientModule
]

Create Angular 8 Service for Accessing RESTful API

Generate an Angular 8 service for Accessing RESTful API by typing this command.

ng g service api

Next, open and edit src/app/api.service.ts then add the below imports.

import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Todo } from './todo';

Then create two constants:

const apiUrl = "http://localhost/curd";

const httpOptions = {
  headers: new HttpHeaders({'Content-Type': 'application/json'})
};

Next, open and edit src/app/api.service.ts then add the below function.

  getTodos (): Observable<Todo[]> {
    return this.http.get<Todo[]>(apiUrl, httpOptions)
      .pipe(
        tap(heroes => console.log('fetched todos')),
        catchError(this.handleError('getTodos', []))
      );
  }

  getTodo(id: number): Observable<Todo> {
    const url = `${apiUrl}?id=${id}`;
    return this.http.get<Todo>(url).pipe(
      tap(_ => console.log(`fetched todo id=${id}`)),
      catchError(this.handleError<Todo>(`getTodo id=${id}`))
    );
  }
  
  addTodo (todo): Observable<Todo> {
    
    return this.http.post<Todo>(`${apiUrl}/create.php`, todo, httpOptions).pipe(
      tap((todo: Todo) => console.log(`added todo w/ id=${todo.id}`)),
      catchError(this.handleError<Todo>('addTodo'))
    );
  }
  
  updateTodo (id, todo): Observable<any> {
    const url = `${apiUrl}/update.php?id=${id}`;
    return this.http.put(url, todo, httpOptions).pipe(
      tap(_ => console.log(`updated todo id=${id}`)),
      catchError(this.handleError<any>('updateTodo'))
    );
  }
  
  deleteTodo (id): Observable<Todo> {
    const url = `${apiUrl}/delete.php?id=${id}`;
  
    return this.http.delete<Todo>(url, httpOptions).pipe(
      tap(_ => console.log(`deleted todo id=${id}`)),
      catchError(this.handleError<Todo>('deletetodo'))
    );
  }
  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
  
      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead
  
      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

Run the below command, will run the Angular 8 Web Application and open the Application in browser by it self

ng serve -o

The Angular 8 crud operation application will looks like

3 Comments

  1. Ricardo said:

    Hi,
    This code is awesome, do you have the backend part in php ?

    October 16, 2019
    Reply
  2. Jamshid said:

    Hi.
    Do you have the video tutorial of this code?
    If yes please share.
    If no please make and share 🙂

    November 1, 2019
    Reply
  3. sonu kumar said:

    not abel to add data any video for this tutorial

    November 4, 2019
    Reply

Leave a Reply

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