Usuwamy zadania za pomocą przycisku


Czyścimy listę | Usuwamy wszystkie zadania

Skoro tak dobrze poszło nam przypisywanie funkcji do przycisków, zróbmy to samo w celu usuwania zadań. Zacznijmy od usunięcia wszystkich zadań na raz za pomocą przycisku wyczyść listę, ponieważ to będzie najłatwiejsze - mamy już gotową funkcję deleteAllTasks(), której nie będziemy nawet modyfikować oraz wiemy, jak przypisać obsługę kliknięcia do elementu HTML. Zmodyfikujmy więc ostatnią linijkę w naszym kodzie HTML:

<!-- poprzedni kod HTML -->

<button onclick="deleteAllTasks()">wyczyść listę</button>

I to tyle! Zapisz plik HTML, otwórz go w przeglądarce, uruchom nasz plik JavaScript w zakładce snippets oraz spróbuj teraz dodać kilka zadań (oczywiście za pomocą przycisku dodaj zadanie), po czym usuń je wszystkie na raz klikając w przycisk wyczyść listę. Nasze 2 (na razie jedyne) przyciski aplikacji działają!

Usuwamy pojedyncze zadania

Jeśli chodzi usunięcie pojedynczego zadania, to sprawa się trochę komplikuje. Przede wszystkim, zauważ, że nie mamy w ogóle przycisku/ów do usuwania poszczególnych zadań! W kursie HTML dodaliśmy taki przycisk do każdego statycznie wpisanego zadania, aczkolwiek później w tym kursie dynamicznie tworzymy nowe zadanie jako element listy, ale bez przycisku.

W związku z tym, musimy zmodyfikować funkcję appendTaskToTheTasksList() w taki sposób, żeby tworząc element listy (zadanie) nie tylko wyświetliła zadanie, ale także wyrenderowała obok niego przycisk do usuwania tego zadania.

Zmodyfikuj funkcję appendTaskToTheTasksList() zgodnie z poniższym kodem - wszelkie szczegóły są wyjaśnione w komentarzach:


// dodaj w nawiasach drugi argument - indeks zadania,
// byśmy mogli go przekazać do deleteTask(), która potrzebuje indeksu
// (pamiętaj, że appendTaskToTheTasksList() jest później przekazana do metody forEach,
// która przekaże 2 argumenty: task i index):
function appendTaskToTheTasksList(task, index) {
  // utwórz nowy element listy li:
  const li = document.createElement("li");
  // i przypisz do niego wartość zadania:

  //====================> ZMODYFIKOWANY KOD: ============================//
  li.textContent = task + " "; // dodajemy spację, by oddzielić tekst od przycisku usuń

  // utwórz przycisk usuwania zadania:
  const deleteButton = document.createElement("button");
  // przypisz do niego nazwę:
  deleteButton.textContent = "usuń";

  // przypisz do niego funkcję usuwania tego konkretnego zadania
  // (to jest nasza istniejąca już funkcja deleteTask())
  deleteButton.onclick = function() {
    deleteTask(index);
  }
  // dodaj przycisk do nowego elementu listy
  li.appendChild(deleteButton); // teraz przycisk będzie dodany po zadaniu po spacji

  //================> KONIEC ZMODYFIKOWANEGO KODU =======================//
  tasksList.appendChild(li);
}

Brawo! Teraz musimy przetestować usuwanie zadań!

W tym miejscu chciałbym dokładniej wyjaśnić, co się dzieje w tym framencie kodu powyższej zmodyfikowanej funkcji:

// ... kod funkcji appendTaskToTheTasksList()...

// przypisz do niego funkcję usuwania tego konkretnego zadania
// (to jest nasza istniejąca już funkcja deleteTask())
deleteButton.onclick = function() {
  deleteTask(index);
}

  // ...dalszy kod funkcji appendTaskToTheTasksList()...

W powyższym kodzie przypisaliśmy funkcję usuwania zadania do atrybutu onclick, ale nie bezpośrednio w HTMLu, jak to robiliśmy wcześniej, tylko za pośrednictwem kodu JavaScript. deleteButton jest zmienną reprezentującą przycisk, w związku z tym mamy dostęp także do atrybutów tego przycisku, tj. np. wspomniany onclick. Po prostu przypisaliśmy do niego wartość w postaci funkcji.

Dlaczego natomiast użyliśmy słowa kluczowego function(), a nie np. po prostu podaliśmy nazwę funkcji? Jest tak dlatego, że gdybyśmy przypisali funkcję z argumentem w ten sposób: deleteButton.onclick = deleteTask(index);, to wyskoczy nam błąd podczas usuwania, ponieważ nie przypisaliśmy tak naprawdę funkcji, ile ją wywołaliśmy wraz z argumentem już w momencie przypisania!

Moglibyśmy z kolei poprawnie przypisać funkcję w ten sposób: deleteButton.onclick = deleteTask;. Jak widzisz, nie ma nawiasów, w związku z tym nie ma błędu i można by było wywołać teraz tę przypisaną funkcję w ten sposób: deleteButton.onclick(index), tyle że nie jesteśmy w stanie tego zrobić, ponieważ deleteButton.onclick zostanie wywołane z poziomu HTML i nie ma jak przekazać tam argumentu index.

W związku z tym przypisaliśmy do deleteButton.onclick deklarację funkcji anonimowej function(){} (anonimowej, czyli nie posiadającej nazwy po słowie kluczowym function), która z kolei wywołuje wewnątrz funkcję deleteTask(index) w momencie, kiedy kliknie się w przycisk.

W nowoczesnym JavaScripcie moglibyśmy to także zrobić prościej, za pomocą funkcji strzałkowej (arrow function): deleteButton.onclick = () => deleteTask(index), aczkolwiek ten zapis również wymagałby wyjaśnienia, natomiast znamy się już na definiowaniu funkcji za pomocą słowa kluczowego function, w związku z czym wybrałem tę opcję.