From cfd2e88765f88aaa9a4355720eb5a86bc6164676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Antonelli?= Date: Mon, 7 Sep 2020 01:14:00 -0300 Subject: [PATCH] Reactive Forms Exercise --- src/app/app-routing.module.ts | 1 - src/app/app.component.html | 26 +--------- src/app/app.component.scss | 8 --- src/app/model/todo-item.ts | 2 + src/app/todo-app/todo-app.component.html | 9 ++-- src/app/todo-app/todo-app.component.ts | 20 ++++--- .../todo-footer/todo-footer.component.html | 2 +- src/app/todo-footer/todo-footer.component.ts | 10 ++-- src/app/todo-form/todo-form.component.html | 38 ++++++++++---- src/app/todo-form/todo-form.component.scss | 12 +++++ src/app/todo-form/todo-form.component.ts | 52 ++++++++++++++++--- src/app/todo-list/todo-list.component.html | 9 ++-- src/app/todo-list/todo-list.component.scss | 14 +++++ src/app/todo-list/todo-list.component.ts | 6 ++- src/app/todo.service.ts | 11 ++-- 15 files changed, 142 insertions(+), 78 deletions(-) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 06c7342..d425c6f 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,6 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; - const routes: Routes = []; @NgModule({ diff --git a/src/app/app.component.html b/src/app/app.component.html index f348a5a..246581b 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,30 +1,6 @@
- -
-
-
-
- - - - -
-
-
- Valido {{profileForm.valid}} - -
- Touched {{profileForm.touched}} -
-
diff --git a/src/app/app.component.scss b/src/app/app.component.scss index c1a2811..e69de29 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,8 +0,0 @@ -input.ng-invalid { - border: 3px solid tomato; -} - -form.ng-invalid { - border-right: 3px solid tomato; - -} \ No newline at end of file diff --git a/src/app/model/todo-item.ts b/src/app/model/todo-item.ts index bdb4f8b..70e92f8 100644 --- a/src/app/model/todo-item.ts +++ b/src/app/model/todo-item.ts @@ -1,6 +1,8 @@ export class TodoItem { id: number; description: string; + url: string; + mail: string; isCompleted: boolean = false; toggleCompleted() { diff --git a/src/app/todo-app/todo-app.component.html b/src/app/todo-app/todo-app.component.html index 786cc57..67dd6f7 100644 --- a/src/app/todo-app/todo-app.component.html +++ b/src/app/todo-app/todo-app.component.html @@ -1,12 +1,11 @@ - + - + - \ No newline at end of file + diff --git a/src/app/todo-app/todo-app.component.ts b/src/app/todo-app/todo-app.component.ts index cc42271..48efaf0 100644 --- a/src/app/todo-app/todo-app.component.ts +++ b/src/app/todo-app/todo-app.component.ts @@ -1,29 +1,37 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, Input } from '@angular/core'; import {TodoItem} from '../model/todo-item'; import { element } from 'protractor'; import { TodoService } from '../todo.service'; -/** */ + @Component({ selector: 'app-todo', templateUrl: './todo-app.component.html', styleUrls: ['./todo-app.component.scss'], }) + export class TodoAppComponent { - constructor( - private service: TodoService - ) {} + @Input() selectedTask:TodoItem; + + constructor(private service: TodoService) {} getList() { return this.service.list; } + onTodoItemRemoved(id) { this.service.remove(id); } + onItemStateChanged(item: TodoItem) { item.toggleCompleted(); } + onTodoItemCreated(task) { - this.service.add(task) + this.service.add(task); + } + + setTaskAsSelected(task) { + this.selectedTask = task; } } diff --git a/src/app/todo-footer/todo-footer.component.html b/src/app/todo-footer/todo-footer.component.html index a0f7423..1a636e3 100644 --- a/src/app/todo-footer/todo-footer.component.html +++ b/src/app/todo-footer/todo-footer.component.html @@ -1,2 +1,2 @@

Tasks Completed {{completedSize()}}

-

Tasks To do {{incompletedSize()}}

+

Tasks To do {{uncompletedSize()}}

diff --git a/src/app/todo-footer/todo-footer.component.ts b/src/app/todo-footer/todo-footer.component.ts index 6e1af04..20f573a 100644 --- a/src/app/todo-footer/todo-footer.component.ts +++ b/src/app/todo-footer/todo-footer.component.ts @@ -15,15 +15,15 @@ export class TodoFooterComponent implements OnInit { private service: TodoService ) { } - ngOnInit() { + ngOnInit() { } - } - incompletedSize() { - this.countTodo = this.service.incompletedSize() + uncompletedSize() { + this.countTodo = this.service.uncompletedSize() return this.countTodo; } + completedSize() { - this.countCompleted =this.service.completedSize() + this.countCompleted = this.service.completedSize() return this.countCompleted; } diff --git a/src/app/todo-form/todo-form.component.html b/src/app/todo-form/todo-form.component.html index ec0ad47..6c20b8c 100644 --- a/src/app/todo-form/todo-form.component.html +++ b/src/app/todo-form/todo-form.component.html @@ -1,10 +1,28 @@ - - - - - - +
+
+ + + + + + +
+
diff --git a/src/app/todo-form/todo-form.component.scss b/src/app/todo-form/todo-form.component.scss index 213bb36..e1028fb 100644 --- a/src/app/todo-form/todo-form.component.scss +++ b/src/app/todo-form/todo-form.component.scss @@ -1,3 +1,15 @@ .add-todo { width: 80% } + +.notValid { + border: 3px solid tomato; +} + +.valid { + border: 3px solid forestgreen; +} + +.formGroup label { + margin-right: 1rem; +} diff --git a/src/app/todo-form/todo-form.component.ts b/src/app/todo-form/todo-form.component.ts index 3366020..ac9866f 100644 --- a/src/app/todo-form/todo-form.component.ts +++ b/src/app/todo-form/todo-form.component.ts @@ -1,5 +1,8 @@ -import { Component, OnInit, Output, EventEmitter} from '@angular/core'; +import { Component, OnInit, Output, EventEmitter, Input} from '@angular/core'; import { TodoItem } from '../model/todo-item'; +import { FormGroup, FormControl, Validators } from '@angular/forms'; +import { TodoService } from '../todo.service'; +import { resetFakeAsyncZone } from '@angular/core/testing'; @Component({ selector: 'app-todo-form', @@ -8,17 +11,52 @@ import { TodoItem } from '../model/todo-item'; }) export class TodoFormComponent { + @Input() selectedTask: TodoItem; @Output() add = new EventEmitter(); + taskForm: FormGroup; + urlRegEx = "^^(ftp|https?):\/\/+(www\.)?[a-z0-9\-\.]{3,}\.[a-z]{3}$"; + mailRegEx = "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"; - save(description){ - if(!description.value || description.value === '') { - return; + constructor(private service:TodoService) { + this.taskForm = new FormGroup({ + id: new FormControl(""), // Hidden + description: new FormControl("", [Validators.required]), + url: new FormControl("", [Validators.required, Validators.pattern(this.urlRegEx)]), + mail: new FormControl("", [Validators.required, Validators.pattern(this.mailRegEx)]), + }) + } + + ngOnChanges(){ + if (this.selectedTask !== undefined && this.selectedTask.id !== null) { + this.taskForm.patchValue({ + id: this.selectedTask.id, + description: this.selectedTask.description, + url: this.selectedTask.url, + mail: this.selectedTask.mail, + }) } + } + + onSubmit(){ let task = new TodoItem(); - task.description = description.value; + task.description = this.taskForm.controls.description.value; task.isCompleted = false; + task.url = this.taskForm.controls.url.value; + task.mail = this.taskForm.controls.mail.value; + if (this.taskForm.controls.id.value) { + task.id = this.taskForm.controls.id.value; + this.service.remove(task.id); + } this.add.emit(task); - description.value = ''; + if (!this.taskForm.controls.id.value) { + console.log(`Item submitted`) + } else { + console.log(`Item ${this.taskForm.controls.id.value} edited successfully`) + } + this.taskForm.reset(); } -} + reset() { + this.taskForm.reset(); + } +} diff --git a/src/app/todo-list/todo-list.component.html b/src/app/todo-list/todo-list.component.html index 127ec76..4422931 100644 --- a/src/app/todo-list/todo-list.component.html +++ b/src/app/todo-list/todo-list.component.html @@ -1,11 +1,12 @@ diff --git a/src/app/todo-list/todo-list.component.scss b/src/app/todo-list/todo-list.component.scss index 0096849..444475a 100644 --- a/src/app/todo-list/todo-list.component.scss +++ b/src/app/todo-list/todo-list.component.scss @@ -1,9 +1,11 @@ .completed { background-color: greenyellow; } + .list { padding: 0; } + .list-item { margin: 0; list-style-type: none; @@ -13,3 +15,15 @@ display: flex; justify-content: space-between; } + +.list a { + text-decoration: none; + color: gray; + cursor: pointer; + transition: all 0.5s; +} + +.list a:hover { + color: blueviolet; + font-size: 105%; +} diff --git a/src/app/todo-list/todo-list.component.ts b/src/app/todo-list/todo-list.component.ts index fc5d8f0..37ed6df 100644 --- a/src/app/todo-list/todo-list.component.ts +++ b/src/app/todo-list/todo-list.component.ts @@ -10,6 +10,7 @@ export class TodoListComponent implements OnInit { @Input() list: any[]; @Output() itemRemoved = new EventEmitter(); @Output() itemStateChanged = new EventEmitter(); + @Output() taskSelected = new EventEmitter(); constructor() { } ngOnInit() { @@ -23,4 +24,7 @@ export class TodoListComponent implements OnInit { } -} \ No newline at end of file + editTask(task){ + this.taskSelected.emit(task); + } +} diff --git a/src/app/todo.service.ts b/src/app/todo.service.ts index 9bba8cc..7e4c9ef 100644 --- a/src/app/todo.service.ts +++ b/src/app/todo.service.ts @@ -7,7 +7,7 @@ import { LocalStorageService } from './local-storage.service'; export class TodoService { list = []; - lastItemId = 0; + lastItemId = 1; constructor(private storage: LocalStorageService) { } @@ -15,7 +15,7 @@ export class TodoService { const id = this.lastItemId; task.id = id; this.list.push(task); - this.lastItemId += 10; + this.lastItemId += 1; } remove(id) { @@ -23,15 +23,16 @@ export class TodoService { this.list.splice(index, 1); } - incompletedSize() { + uncompletedSize() { return this.list.filter(item => !item.isCompleted).length; } + completedSize() { - return this.list.filter(item => item.isCompleted).length ; + return this.list.filter(item => item.isCompleted).length; } getName() { - return 'TodoService 123' + this.storage.getName(); + return 'ToDoService' + this.storage.getName(); } }