W poprzednich artykułach stworzyliśmy nasz pierwszy komponent dla aplikacji – listę to do oraz dodaliśmy do niej zadania. Następnie rozszerzyliśmy aplikację o listę zadań zrobionych, korzystając z stworzonych wcześniej komponentów.
Stworzyliśmy model naszego zadania i stwierdziliśmy, że potrzebujemy czegoś „zarządzającego” listą zadań, która jest współdzielona dla całej aplikacji. W tym celu stworzyliśmy serwis.
Nasza aplikacja świetnie wyświetla listę zadań do zrobienia oraz tych zrobionych. Jednak na co lista to do do której nie można nic dodać? Czas się tym zająć.
Wymagania wstępne:
Spisane w formie checklisty (do wydrukowania bądź podglądu/importu jako szablon Nozbe):
Materiały do nauki oraz informacje co i jak znajdziesz we wpisie Tworzymy aplikację webową – krok po kroku – podsumowanie aktualnego statusu & co dalej?
Branch, odpowiadający dzisiejszemu artykułowi: 06-add-new-todo
Chcemy dodawać nowe zadania do listy. Czego potrzebujemy?
Po pierwsze miejsca, gdzie moglibyśmy wpisać nowe zadanie.
AddNewTodoComponent
Załóżmy, że będzie to oddzielny komponent, składający się z dwóch elementów: miejsca na wpisanie zadania oraz przycisku dodającego je do listy.
Komponent nazwiemy AddNewTodo.
Mam nadzieję, że nie muszę Ci pisać jak stworzyć nowy komponent? Jeśli tak – cofnij się do artykułu Template, Component, Data Binding & nasz pierwszy komponent.
Struktura tego komponentu przedstawia się następująco:
1 2 3 4 |
<div> <input #newTaskName (keyup.enter)="addTodo(newTaskName.value); newTaskName.value = ''"> <button (click)="addTodo(newTaskName.value); newTaskName.value = ''">+</button> </div> |
Pierwszym elementem, który zauważamy jest #newTaskName. #var to tzw. template reference variable – zmienna odnosząca się do elementu w szablonie (template) naszego komponentu. W tym przypadku #newTaskName deklaruje zmienną newTaskName, która wskazuje na input.
Możemy z tej zmiennej korzystać. Odczytajmy więc zawartość pola input (newTaskName.value) i przekażmy jako parametr funkcji addTodo().
Fajnie by było również stworzyć funkcję addTodo(). Na początek niech wypisuje w konsoli zawartość pola Input.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-add-new-todo', templateUrl: './add-new-todo.component.html', styleUrls: ['./add-new-todo.component.scss'] }) export class AddNewTodoComponent implements OnInit { constructor() { } ngOnInit() { } addTodo(taskName) { console.log(taskName); } } |
Działa? Działa. W konsoli ukaże się nazwa stworzonego zadania.
Aaa… tak. Kiedy? No cóż, możemy ją wypisać na dwa sposoby. Z jednej strony Button ma metodę (click), która wywołuje metodę addTodo() oraz czyści pole Input, tak by było możliwe wpisanie kolejnego zadania. Z drugiej metoda (keyup.enter) podpięta pod Input reaguje identycznie na wciśnięcie klawisza Enter.
Rozszerzamy TodoService & Dodajemy nowe zadanie
W konsoli ukaże się wpisane zadanie. Super! Ale chyba nie o to nam chodzi. Chcielibyśmy by zadanie dodało się do listy. Jak to zrobić?
W poprzednim artykule tworzyliśmy serwis – TodoService. Powiedzieliśmy sobie, że to on będzie zarządzał naszymi listami zadań. Jak na razie jego głównym zadaniem było zwracanie zadań.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import { EventEmitter } from '@angular/core'; import { Todo } from './todo.model'; export class TodoService { todoChanged = new EventEmitter<Todo[]>(); private tasks: Todo[] = [ new Todo('Todo #11'), new Todo('Todo #12'), new Todo('Todo #13'), new Todo('Todo #14'), new Todo('Todo #15', true), new Todo('Todo #16', true) ]; getTasks() { return this.tasks; } getTodos() { return this.tasks.filter(task => !task.done); } getDoneTasks() { return this.tasks.filter(task => task.done); } } |
No ale skądś się tam muszą wziąć. Czas dodać metodę dodawania nowych zadań.
Załóżmy, że do listy dodajemy zadania. Nie tworzymy ich w samym serwisie. Złożenie zadania to już odpowiedzialność poszczególnych komponentów. O czym mówię? To komponent na podstawie nazwy zadania, stworzy jego instancję:
1 |
var newTask = new Todo(taskName); |
Tylko jeden parametr? To już wynika z modelu naszego zadania. Przypomnę:
1 2 3 4 5 6 7 8 9 |
export class Todo { public name: string; public done: boolean; constructor(name: string, done: boolean = false) { this.name = name; this.done = done; } } |
Konstruktor przyjmuje dwa argumenty. Jednak drugi z nich jest opcjonalny, domyślnie równy false. Dlaczego false, a nie true – mam nadzieję nie muszę tłumaczyć?
Mamy nowe zadanie. Tak jak wspominałam, jego stworzeniem zajmie się nasze komponent. A więc rozszerzamy metodę addTodo() komponentu AddNewTodo:
1 2 3 4 |
addTodo(taskName) { console.log(taskName); var newTask = new Todo(taskName); } |
Czyli mamy nowe zadanie, które chcemy dodać do naszej listy. Wracamy do serwisu TodoService. Jak dodać zadanie do listy? Korzystając z metody push().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export class TodoService { todoChanged = new EventEmitter<Todo[]>(); private tasks: Todo[] = [ new Todo('Todo #11'), new Todo('Todo #12'), new Todo('Todo #13'), new Todo('Todo #14'), new Todo('Todo #15', true), new Todo('Todo #16', true) ]; addTodo(todo) { this.tasks.push(todo); } |
Ok. Zadanie dodane.
Jednak hallo! Zadanie zniknęło. Ale nie pojawiło się na żadnej liście…
Jeśli uważnie czytaliście poprzedni artykuł domyślacie się pewnie dlaczego? Tak, komponenty list muszą odświeżyć swoją zawartość. Są zasubskrybowane na zmiany w serwisie, ale serwis musi dać znać o tym, że takie zmiany nastąpiły. W tym celu skorzystamy z EventEmitter’a oraz metody emit():
1 2 3 4 |
addTodo(todo) { this.tasks.push(todo); this.todoChanged.emit(); } |
Nowe zadanie pojawi się na liście.
To już niemal koniec sezonu drugiego tej serii. Mamy aplikację, która wyświetla listę zadań, pozwala zaznaczać/odznaczać wykonanie, dodawać nowe zadania do listy. Przy jej okazji omówiliśmy temat tworzenia nowych komponentów, podstawowe zagadnienia dotyczące Angular v4. Niewiele już nam zostało… ale o tym wkrótce.
Przypominam, że kod aplikacji po dzisiejszej lekcji znajdziesz na Github’ie, branch: 06-add-new-todo
W razie pytań – śmiało dawaj znać w komentarzu lub na naszej Tutorialowej Grupie Wsparcia na Facebooku.
Powodzenia!