How to implement CRUD To-do Application in Angular 8?

In this tutorial Angular 8 CRUD tutorial, we will learn how to implement CRUD To-do Application in Angular 8.

Befor get started with angular 8 crud operation. You must have installed Angular 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

],

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

<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 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

#Angular #webdev #javascript

How to implement CRUD To-do Application in Angular 8?
12.55 GEEK