This tutorial is an Angular version of the plain Javascript one.(https://dev.to/zoltanhalasz/full-stack-mini-todo-app-with-javascript-ajax-api-controller-and-in-memory-database-asp-net-core-razor-pages-2bbf)
The back-end will be exactly identical, for simplicity will call the API from the previous tutorial, please study the above link for this.
The application was created from scratch, new Angular 9 application, with some inspiration from the below Angular HttpClient tutorial.
Prerequisites:
- you must have Angular 9 (or 7,8) installed on your PC
- basic / intermediate javascript/typescript
- review above mentioned tutorials. Web api for back-end is identical.
- the front-end, styling belong to original tutorial from Dennis Ivy, I just transposed here to Angular. https://youtu.be/hISSGMafzvU
- basic tutorial for Angular, which teaches some of the steps: https://www.positronx.io/angular-7-httpclient-http-service/
Application is live under: https://angulartodo.zoltanhalasz.net/
Zip Repo: here. https://drive.google.com/open?id=1CvS8G3Hj9g-HJgQjTyCXW6nkA4j_ff5M
Steps for creating the app:
a. ng new todolist
b. styling
add bootstrap:
npm install bootstrap
css file include it in Angular.json
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"styles.scss"
]
in the index html file, I will include some special fonts in the head
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
app.component.css will include the formatting from Dennis Ivy's original tutorial.(see repo)
c. create class
export class todomodel {
constructor (
public id: number,
public title: string,
public completed: boolean){
}
}
d. create service - I will not copy the lengthy code here.(see repo)
Some starting points: it is a very close copy of the api service from this tutorial (also mentioned above): https://www.positronx.io/angular-7-httpclient-http-service/
The Api link reference will be identical with the plain javascript tutorial.
'https://todolist.zoltanhalasz.net/api/TodoModels'
e. add various references to app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { TodoService } from './todo.service';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule
],
providers: [TodoService],
bootstrap: [AppComponent]
})
export class AppModule { }
f.app component html
<div class="container">
<div id="task-container">
<div id="form-wrapper">
<form id="form" (ngSubmit)="onSubmit()" #todoForm="ngForm">
<div class="flex-wrapper">
<div style="flex: 6">
<input type="text" class="form-control" id="title" required [(ngModel)]="mytodo.title" name="title"
#title="ngModel">
</div>
<div style="flex: 1">
<button type="submit" id="submit" class="btn">Submit</button>
</div>
</div>
</form>
</div>
<div id="list-wrapper">
<div class="task-wrapper flex-wrapper" *ngFor="let item of mytodolist">
<div style="flex:7">
<span [className]="item.completed ? 'finish-title' : 'title'"
(click)="FinishTodo(item.id)">{{item.title}}</span>
</div>
<div style="flex:1">
<button class="btn btn-sm btn-outline-info edit" (click)="Edit(item.id)">Edit </button>
</div>
<div style="flex:1">
<button class="btn btn-sm btn-outline-danger delete" (click)="Delete(item.id)">Delete</button>
</div>
</div>
</div>
</div>
</div>
g. app.component.ts
import { Component, OnInit } from '@angular/core';
import {todomodel} from "./todomodel";
import { TodoService } from './todo.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
title = 'todolist';
// when a task is being edited
edited = false;
// initialize sample todo
mytodo = new todomodel(0,'',false);
// this array will always store list of todos retrieved from server
mytodolist: todomodel [];
//injecting the dataservice
constructor (private dataservice: TodoService) {
}
// submitting the form
onSubmit() {
this.saveTodo(this.mytodo);
// resetting the mytodo value
this.mytodo = new todomodel(0,'',false);
}
saveTodo(mytodo: todomodel){
// if it is not an editing
if (!this.edited) {
if (this.mytodo.title=='') return;
// saving new todo
this.dataservice.createTodo(mytodo).subscribe(data=> {
this.displayTodoList();
});
}
// if we are editing an existing todo
else {
this.edited=false;
console.log('this is being edited',mytodo);
// update existing todo
this.dataservice.updateTodo(this.mytodo.id,this.mytodo).subscribe(data =>
{
this.displayTodoList();
}
);
}
}
ngOnInit(){
this.displayTodoList();
}
//this function retrieves the whole array of todos from server, using api service injected
displayTodoList() {
this.dataservice.getTodoList().subscribe(data =>
{
// as the Web Api doesn't sort the list of todos, we do here in the frontend
this.mytodolist = data.sort((a,b)=> {
if (a.id>b.id) return -1;
if (a.id<b.id) return 1;
});
console.log('display', this.mytodolist);
});
}
//deleting an existing todo
Delete(id: number) { // without type info
console.log('delete', id);
this.dataservice.deleteTodo(id).subscribe(data =>{
this.displayTodoList();
});
}
//editing an existing todo
Edit(eid: number) { // without type info
console.log('editing',eid);
this.mytodo = this.mytodolist.filter(x=>x.id ==eid)[0];
this.edited = true;
}
//finalizing(crossing) an existing todo
FinishTodo(eid: number) { // without type info
// console.log('finishing', eid);
const mytodofinished = this.mytodolist.filter(x=>x.id ==eid )[0];
mytodofinished.completed = !mytodofinished.completed ;
//calling the update observable
this.dataservice.updateTodo(eid,mytodofinished).subscribe(data =>{
this.displayTodoList();
});
}
}
Top comments (0)