Angular Series Part 5 - Create a TODO App
Post last updated: December 31, 2022
How to create a TODO Application with Angular Step by Step
With all the theoretical Knowledge we have learned, we are goind to create a wonderful todo app. Please follow the steps along
1. Create a new Angular project by running the following command in your terminal:
ng new todo-app
2. Install Angular Material and the Angular CDK by running the following command in your terminal:
npm install --save @angular/material @angular/cdk
3. Import the MatButtonModule
, MatCardModule
, MatDialogModule
, and MatFormFieldModule
from the @angular/material
module in your application's root module (e.g. app.module.ts):
import {
MatButtonModule,
MatCardModule,
MatDialogModule,
MatFormFieldModule
} from '@angular/material'
4. Add the imported modules to the imports array of your application's root module:
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
MatButtonModule,
MatCardModule,
MatDialogModule,
MatFormFieldModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
5. Create a service to manage the todos by running the following command in your terminal:
ng generate service todo
6. In the todo.service.ts
file, define an array of todo objects and add methods to add, remove, and update todos:
import { Injectable } from '@angular/core'
@Injectable({
providedIn: 'root'
})
export class TodoService {
todos: any[] = [
{ id: 1, title: 'Todo 1', description: 'Description 1' },
{ id: 2, title: 'Todo 2', description: 'Description 2' },
{ id: 3, title: 'Todo 3', description: 'Description 3' }
]
constructor() {}
getTodos() {
return this.todos
}
addTodo(todo) {
this.todos.push(todo)
}
removeTodo(todo) {
const index = this.todos.indexOf(todo)
this.todos.splice(index, 1)
}
updateTodo(todo) {
const index = this.todos.indexOf(todo)
this.todos[index] = todo
}
}
7. Create a component for the todo list by running the following command in your terminal:
ng generate component todo-list
8. In the todo-list.component.ts
file, inject the TodoService
and use the service's methods to get, add, remove, and update todos:
import { Component, OnInit } from '@angular/core';
import { TodoService } from '../todo.service';
@Component({
selector: 'app-todo-list',
templateUrl: './todo-list.component.html',
styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent implements OnInit {
todos: any[];
constructor(private todoService: TodoService) { }
ngOnInit() {
this.todos = this.todoService.getTodos();
}
addTodo(todo) {
this.todoService.addTodo(todo);
}
removeTodo(todo) {
this.todoService.removeTodo(todo);
}
updateTodo(todo) {
this.todoService.updateTodo(todo);
}
}
9. In the todo-list.component.html
file, use the *ngFor
directive to iterate over the todos and display them in a list, and use the component's methods to add, remove, and update todos:
<ul>
<li *ngFor="let todo of todos">
{{ todo.title }}
<button (click)="removeTodo(todo)">Remove</button>
</li>
</ul>
<button (click)="openAddDialog()">Add todo</button>
<mat-dialog-container>
<mat-dialog #addDialog>
<form #addForm="ngForm" (ngSubmit)="addTodo(addForm.value)">
<mat-form-field>
<input
matInput
type="text"
name="title"
ngModel
required
placeholder="Title"
/>
</mat-form-field>
<mat-form-field>
<input
matInput
type="text"
name="description"
ngModel
required
placeholder="Description"
/>
</mat-form-field>
<button mat-button type="submit">Add</button>
</form>
</mat-dialog>
</mat-dialog-container>
<mat-dialog-container>
<mat-dialog #updateDialog>
<form #updateForm="ngForm" (ngSubmit)="updateTodo(updateForm.value)">
<mat-form-field>
<input
matInput
type="text"
name="title"
[(ngModel)]="selectedTodo.title"
required
placeholder="Title"
/>
</mat-form-field>
<mat-form-field>
<input
matInput
type="text"
name="description"
[(ngModel)]="selectedTodo.description"
required
placeholder="Description"
/>
</mat-form-field>
<button mat-button type="submit">Update</button>
</form>
</mat-dialog>
</mat-dialog-container>
10. In the todo-list.component.ts
file, add methods to open the add and update dialogs and select a todo for updating:
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material';
import { TodoService } from '../todo.service';
@Component({
selector: 'app-todo-list',
templateUrl: './todo-list.component.html',
styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent implements OnInit {
todos: any[];
selectedTodo: any;
constructor(private todoService: TodoService, private dialog: MatDialog) { }
ngOnInit() {
this.todos = this.todoService.getTodos();
}
openAddDialog() {
this.dialog.open(this.addDialog);
}
openUpdateDialog(todo) {
this.selectedTodo = todo;
this.dialog.open(this.updateDialog);
}
addTodo(todo) {
this.todoService.addTodo(todo);
this.dialog.closeAll();
}
removeTodo(todo) {
this.todoService.removeTodo(todo);
}
updateTodo(todo) {
this.todoService.updateTodo(todo);
this.dialog.closeAll();
}
}
11. Create a component for the todo detail page by running the following command in your terminal:
ng generate component todo-detail
12. In the todo-detail.component.ts
file, inject the TodoService and use the service's methods to get and update a todo:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { TodoService } from '../todo.service';
@Component({
selector: 'app-todo-detail',
templateUrl: './todo-detail.component.html',
styleUrls: ['./todo-detail.component.css']
})
export class TodoDetailComponent implements OnInit {
todo: any;
constructor(private route: ActivatedRoute, private todoService: TodoService)
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.todo = this.todoService.getTodos().find(todo => todo.id === id);
}
updateTodo(todo) {
this.todoService.updateTodo(todo);
}
}
13. In the todo-detail.component.html
file, use the [(ngModel)]
directive to bind the todo object to a form for updating:
<form #updateForm="ngForm" (ngSubmit)="updateTodo(updateForm.value)">
<mat-form-field>
<input
matInput
type="text"
name="title"
[(ngModel)]="todo.title"
required
placeholder="Title"
/>
</mat-form-field>
<mat-form-field>
<input
matInput
type="text"
name="description"
[(ngModel)]="todo.description"
required
placeholder="Description"
/>
</mat-form-field>
<button mat-button type="submit">Update</button>
</form>
14. In the app.module.ts
file, import the RouterModule and Routes from the @angular/router module
, and define routes for the todo list and todo detail pages:
import { RouterModule, Routes } from '@angular/router'
const routes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: 'todos', component: TodoListComponent },
{ path: 'todo/:id', component: TodoDetailComponent }
]
@NgModule({
declarations: [AppComponent, TodoListComponent, TodoDetailComponent],
imports: [
BrowserModule,
MatButtonModule,
MatCardModule,
MatDialogModule,
MatFormFieldModule,
RouterModule.forRoot(routes)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
15. In the app.component.html
file, use the router-outlet directive to display the active route:
<router-outlet></router-outlet>
You can watch a complete video tutorial here! :)