W poprzednich artykułach stworzyliśmy nasz pierwszy komponent dla aplikacji – listę „to do” oraz dodaliśmy do niej zadania.
W aplikacjach tego typu często poza listą „do zrobienia”, mamy również listę „zrobione”. Jak wykorzystać dotychczas stworzone komponenty i rozszerzyć aplikację o drugą listę?
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: 04-todo-model
Lista „Done”
Poza listą To do, mamy jeszcze listę Done. Jak ją stworzyć wykorzystując nasze komponenty?
Duplikujemy fragment odpowiedziany za dodanie listy To do (app.component.html):
1 2 |
<app-todo-list [list]="lists.todo"></app-todo-list> <app-todo-list [list]="lists.done"></app-todo-list> |
oraz tworzymy listę analogiczną do To do w app.component.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
lists = { todo: { name: 'To do', tasks: [ 'Todo #1', 'Todo #2', 'Todo #3', 'Todo #4' ] }, done: { name: 'Done', tasks: [ 'Todo #5', 'Todo #6' ] } } |
Efekt?
No, nie do końca o to nam chodziło. Chcieliśmy, żeby zadania wykonane były przekreślone. Ale właściwie skąd aplikacja ma wiedzieć, że zadania są wykonane?
Potrzebujemy właściwości dla zadań: statusu.
Założmy, że interesują nas tylko dwa statusy: to do i done. Możemy więc wprowadzić parametr done z wartościami true/false, opisujący stan realizacji zadania.
W tym celu musimy również nieco zmodyfikować naszą listę zadań. Poza nazwą powinna zawierać również status, a więc być obiektem zamiast string’iem.
Po pierwsze modyfikujemy więc dane wejściowe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
lists = { todo: { name: 'To do', tasks: [ {name: 'Todo #1', done: false}, {name: 'Todo #2', done: false}, {name: 'Todo #3', done: false}, {name: 'Todo #4', done: false}, ] }, done: { name: 'Done', tasks: [ {name: 'Todo #5', done: true}, {name: 'Todo #6', done: true} ] } } |
Po drugie todoItem component:
1 2 3 4 |
<div> <input type="checkbox"> <label>{{ task.name }}</label> </div> |
Musi wyświetlać task.name. Pozostawienie tam task, spowoduje wyświetlenie [Object object].
Teraz musimy przekazać dalej ten status do komponentu listy, a stamtąd komponentu elementu listy. Zaraz… my już to przecież mamy 🙂
Komponent TodoListItem dostaje na wejściu cały obiekt zadania, a więc i własność „done”. Wystarczy tylko ją wykorzystać. Na co ma mieć wpływ?
- checkbox – zaznaczony
- nazwa zadania – przekreślona
W przypadku pola input musimy ustawić atrybut checked na odpowiednią wartość. Skorzystamy z property binding:
1 |
<input type="checkbox" [checked]="task.done"> |
W przypadku nazwy zadania – przekreślenie uzyskamy dodając odpowiednią klasę w zależności od status zadania. Możemy to zrobić z wykorzystaniem ngClass:
1 |
<label [ngClass]="{'taskIsDoneDecoration': task.done}">{{ task.name }}</label> |
Oczywiście wcześniej musimy zdefiniować klasę taskIsDoneDecoration w pliku .scss:
1 2 3 |
.taskIsDoneDecoration { text-decoration: line-through; } |
Rezultat?
Żeby nie było za pięknie – czas nieco posprzątać.
Za chwilę będziemy dodawać zadania do listy. Przydałoby się wyodrębnić model takiego zadania.
Todo Model
Dla odróżnienia plik z modelem nazwiemy: todo.model.ts.
Załóżmy, że będzie współdzielony w całej aplikacji. Umieśćmy go w nowo stworzonym folderze shared.
Jak będzie wyglądał model Todo?
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; } } |
Korzystając z takiego modelu, tworzymy nasze zadania w następujący sposób:
1 |
new Todo('Todo #11') |
Nie musimy deklarować statusu zadania. Jeśli go brakuje – domyślnie ustawiany jest na „false”. Oczywiście, jeśli chcemy by status był ustawiony na true – musimy to powiedzieć.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
lists = { todo: { name: 'To do', tasks: [ new Todo('Todo #11'), new Todo('Todo #12'), new Todo('Todo #13'), new Todo('Todo #14') ] }, done: { name: 'Done', tasks: [ new Todo('Todo #15', true), new Todo('Todo #16', true) ] } } |
Oczywiście, jeśli chcemy w ogóle z niego skorzystać, musimy go najpierw zaimportować w miejscu wykorzystania:
1 |
import {Todo} from './shared/todo.model'; |
Ale czy to naprawdę powinno tak wyglądać? Przecież status możemy zmieniać (done/undone). Tak naprawdę potrzebujemy jednej listy zadań, nie dwóch. Oraz sposobu by zwracać listę w zależności od danego parametru. Za chwilę będziemy również tworzyć formularz dodawania nowych zadań, który musi operować na tej samej liście. Czegoś nam brakuje…
Czymś tym jest serwis. Którym zajmiemy się w kolejnym artykule serii!
Przypominam, że kod aplikacji po dzisiejszej lekcji znajdziesz na Github’ie, branch: 04-todo-model
W razie pytań – śmiało dawaj znać w komentarzu lub na naszej Tutorialowej Grupie Wsparcia na Facebooku.
Powodzenia!
P.S.
Mam pytanie: jak Ci pasuje aktualna forma tutorialu?
W planach dotyczących przyszłości bloga wspominałam, że chcę wejść na Youtube. Filmiki, tutoriale, live coding. Myślę, by w ten sposób zrealizować kolejną część (sezon III) tutorialu. Być może nawet przerobić tą. Tj. już teraz ukaże się do końca w formie pisemnej, raczej przerobiłabym ją z czasem.
Oczywiście nie byłaby to seria w 100% video. Ukazywałyby się wpisy z min. jednym filmikiem w temacie, ale do tego linki do materiałów, treści dodatkowe, fragmenty kodu, itp.
Ciekawi mnie Twoje zdanie w tym temacie. A może wolisz wersję pisemną tutorialu? Nie video? Video wbrew pozorom ma swoje minusy. Jestem tego świadoma.
Masz może do mnie jakieś uwagi? Czegoś nie lubisz w video? Na coś uważać?
Daj znać w komentarzu bądź ankiecie 🙂 (w obu miejscach również mile widziane 🙂 )