Mörkt tema
đ§âđ To do-app â
En liten to do-app pÄ under 20 steg!
Introduktion â
Du kan anvÀnda denna uppgift för att "förankra" koncepten. Det Àr en steg-för-steg-guide för att skapa en liten to do-app.
Uppgiftsbeskrivning â
I uppgiften ska vi skapa en att göra-lista. Följande "krav" finns:
- Det ska gÄ att lÀgga till en uppgift i listan.
- Det ska gÄ att markera en uppgift som klar/ej klar.
Steg-för-steg â
1. Skapa filer
För uppgiften behöver vi tvÄ filer:
index.htmldÀr vi skriver vÄr HTML-kod och dÀr vi lÀnkar in vÄr JavaScript-filscript.jsdÀr vi skriver vÄr JavaScript-kod.- Bonus:
style.cssom du vill göra sidan lite trevligare, men inget krav!
Skapa dessa tvÄ (tre) filer i samma mapp och koppla ihop dessa enl. praxis.
html
<!doctype html>
<html>
<head>
<title>Att göra-listan</title>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<!-- HTML-kod skrivs hÀr -->
<script src="script.js"></script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
2. Skapa ett formulÀr för uppgifter
NÀsta steg Àr att i HTML-filen skapa en input-ruta (för text) dÀr man kan skriva uppgiftens "namn".
Ge input-rutan ett id-attribut, t.ex. id="taskName".
Skapa ocksÄ en knapp och ge den ett id ocksÄ, t.ex. createTaskBtn.
Din HTML kanske ser ut sÄhÀr:
html
<form>
<label>
<span>Uppgiftsbeskrivning</span>
<input type="text" id="taskName">
</label>
<input type="button" value="Skapa uppgift" id="createTaskBtn">
</form>1
2
3
4
5
6
7
2
3
4
5
6
7
3. Koppla event till DOM
Nu ska vi skapa en koppling mellan input-fÀltet, knappen och JavaScript. Först ska vi testa att det ens fungerar!
I script.js skriver vi:
javascript
// Vi skapar en funktion som i framtiden ska lÀgga till uppgifter
// i vÄr att göra-lista, men just nu kommer den bara skriva ut ett
// meddelande till konsolen. Vi vill testa att knapp-klick funkar som
// tÀnkt innan vi gÄr vidare.
function createNewTask() {
console.log('Create new task!');
}
// Vi letar reda pÄ knappen i vÄrt HTML-dokument med querySelector
// och sparar det i en variabel sÄ att vi snabbt kan "komma Ät den"
const createTaskBtn = document.querySelector('#createTaskBtn');
// Sedan kopplar vi pÄ en eventlyssnare som vÀntar pÄ att anvÀndaren
// ska klicka pÄ knappen
createTaskBtn.addEventListener('click', createNewTask);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Prova sedan att klicka pÄ knappen, och öppna inspektorn och se om meddelandet dök upp dÀr.
Om det gjorde det - toppen! Annars fÄr du felsöka.
- Kan du ha stavat nÄgonting fel?
- Ăr alla filer sammankopplade rĂ€tt?
- Har du sparat alla filer efter att du gjort Àndringar?
4. Ta reda pÄ uppgiftsbeskrivningen
Nu vill vi modifiera vÄr kod sÄ att vi Àven fÄr information om vad det Àr för uppgift vi ska skapa.
Modifiera funktionen createNewTask sÄ att den ser ut som nedan, och testa att det fungerar!
Vi förvÀntar oss att det som stÄr i input-rutan nu ska synas i konsolen, nÀr vi klickar pÄ knappen.
javascript
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
console.log('Create new task:', newTaskDescription);
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);1
2
3
4
5
6
7
2
3
4
5
6
7
Om allt fungerar som det ska sĂ„ kan vi gĂ„ vidare! đ
5. Skapa en variabel för alla vÄra uppgifter
Nu behöver vi nÄgonstans att spara vÄra uppgifter⊠det ska vi göra i en array!
Högst upp i script.js, lÀgg till:
javascript
const tasks = [];
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
console.log('Create new task:', newTaskDescription);
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
6. Spara uppgiften till vÄr lista
En tom array gör vi inte mycket med! Nu ska vi fÄ in den text som stÄr i input-rutan in i arrayen!
För det behöver vi anvÀnda push till en array, sÄ att den sparas i listan.
Varje uppgift behöver ocksÄ tvÄ egenskaper: dess namn och om den Àr klar eller inte. Ett objekt lÀmpar sig vÀl för detta.
javascript
const tasks = [];
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
// Skapa en ny uppgift & lÀgg till i listan
const newTask = {
description: newTaskDescription,
done: false,
};
tasks.push(newTask);
console.table(tasks);
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Prova att lÀgga till 2-3 uppgifter och verifiera att du fÄr ut dessa i konsolen i DevTools.
7. Recap
Vad har vi gjort hittills? Reflektera gÀrna sjÀlv en stund innan du lÀser vidare.
Vilka koncept har du nu provat pÄ? Vad gjorde dessa? Hur hÀngde allt ihop? Vad var flödet?
Skulle du kunna Äterskapa detta frÄn scratch pÄ egen hand? Prova gÀrna!
Repetition Àr kunskapens moder!
8. Recap (facit)
Vi har (exempelvis):
- Skapat en koppling mellan DOM och JavaScript
- Lagt till en eventlyssnare pÄ knappen
- Skapat en variabel dÀr vi kan spara vÄra uppgifter
- Skapat en funktion som hanterar att lÀgga till uppgifter i listan
- Skapat nya objekt (todos)
9. Visa uppgifterna i HTML, steg 1
Kul med virtuella uppgifter. Ănnu roligare om vi faktiskt kunde se dessa i vĂ„rt HTML-dokument ju, i "realtid"!
I HTML, lÀgg till en <div> och ge den ett id, t.ex. tasklist:
html
<div id="tasklist"></div>1
10. Visa uppgifterna i HTML, steg 2
Nu behöver vi uppdatera/Àndra innehÄllet i div:en varje gÄng vi lÀgger till en ny uppgift i vÄr lista!
Vi vill gÀrna ha en "separation of concerns" nÀr det gÀller funktioner. En funktion ska göra en sak (och göra det bra).
Vi behöver en referens till vÄr "platshÄllare", dÀr uppgifterna ska visas, och en ny funktion i vÄrt JavaScript-dokument som ansvarar för att skriva ut uppgifterna i HTML-dokumentet:
javascript
const tasks = [];
const tasklistDiv = document.querySelector('#tasklist');
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task) => {
htmlCode += `<li>${task.description} - Klar: ${task.done}</li>`;
});
htmlCode += '</ul>';
tasklistDiv.innerHTML = htmlCode;
}
// Ăvrig kod som fanns sedan innan1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Prova sedan om uppgifterna dyker upp i HTML-dokumentet nÀr du lÀgger till en ny uppgift?
NĂ€hĂ€, inte? Vad trĂ„kigt! Vad kan vi ha glömt? đ
11. Visa uppgifterna i HTML, steg 3
AnvÀnder vi funktionen printTasks() nÄgonstans? Eller har vi bara definierat den?
Var vore det rimligt att den anropades? TÀnk sjÀlv innan du gÄr vidare!
12. Visa uppgifterna i HTML, steg 4
Din kod borde nu se ut sÄhÀr i sin helhet, typ:
javascript
const tasks = [];
const tasklistDiv = document.querySelector('#tasklist');
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task) => {
htmlCode += `<li>${task.description} - Klar: ${task.done}</li>`;
});
htmlCode += '</ul>';
tasklistDiv.innerHTML = htmlCode;
}
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
// Skapa en ny uppgift & lÀgg till i listan
const newTask = {
description: newTaskDescription,
done: false,
};
tasks.push(newTask);
console.table(tasks);
printTasks();
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);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
29
30
31
32
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
29
30
31
32
13. En knapp för att markera uppgiften fÀrdig
HÀrnÀst vore det vÀl kul om vi kunde "toggla" en uppgift som klar eller ofÀrdig?
Vi behöver modifiera utskriften sÄ att vi fÄr ut en knapp, istÀllet för bara texten "false":
javascript
const tasks = [];
const tasklistDiv = document.querySelector('#tasklist');
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task) => {
htmlCode += `<li>
${task.description}
<button>Klar</button>
</li>`;
});
htmlCode += '</ul>';
tasklistDiv.innerHTML = htmlCode;
}
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
// Skapa en ny uppgift & lÀgg till i listan
const newTask = {
description: newTaskDescription,
done: false,
};
tasks.push(newTask);
console.table(tasks);
printTasks();
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);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
29
30
31
32
33
34
35
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
29
30
31
32
33
34
35
14. Gör nÄgot med klar-knappen
Kul med knapp, Ă€nnu roligare om den gjorde nĂ„got nĂ€r vi klickade pĂ„ denâŠ
Vi behöver koppla pÄ en eventlyssnare pÄ alla "Klar"-knappar. Men⊠hur ska vi göra det pÄ ett effektivt sÀtt? Vi kan ju inte veta hur mÄnga uppgifter det finns i förvÀg.
Vi behöver alltsÄ skapa eventlyssnarna dynamiskt, baserat pÄ vilka uppgifter vi har i vÄr lista.
Tricket för att göra det Àr att, efter att knapparna har skapats, leta reda pÄ dessa nu nÀr de existerar i DOM:en, och lÀgga pÄ en eventlyssnare.
För att vara effektiva behöver vi anvÀnda oss av en loop.
Och kom ihÄg⊠en funktion = en uppgift. Typ sÄhÀr:
javascript
const tasks = [];
const tasklistDiv = document.querySelector('#tasklist');
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task) => {
htmlCode += `<li>
${task.description}
<button>Klar</button>
</li>`;
});
tasklistDiv.innerHTML = htmlCode;
addDoneBtnClickEvents();
}
function addDoneBtnClickEvents() {
const doneButtons = document.querySelectorAll('button');
doneButtons.forEach((btn) => {
btn.addEventListener('click', toggleTaskStatus);
});
}
function toggleTaskStatus() {
console.log('Task is done!');
}
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
// Skapa en ny uppgift & lÀgg till i listan
const newTask = {
description: newTaskDescription,
done: false,
};
tasks.push(newTask);
console.table(tasks);
printTasks();
}
const createTaskBtn = document.querySelector('#createTaskBt1
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Prova nu att lÀgga till 2-3 uppgifter igen och testa att dessa skriver ut att uppgiften Àr klar i konsolen.
15. Vilken uppgift Àr klar?!
Men⊠hur ska vi fÄ reda pÄ vilken uppgift som Àr klar? Visst vore det praktiskt om alla uppgifterna blev klara bara för att man gjorde klart en, men sÄ funkar det ju tyvÀrr inte IRL/AFK.
Ugh, vi behöver nÄgot sÀtt att skapa en distinktion mellan de olika uppgifterna. Klurigt!
Vi skulle kunna gÄ pÄ uppgiftens beskrivning, men om man t.ex. lÀgger till "Köp mjölk" tvÄ gÄnger i listan, sÄ kan vi inte sÀrskilja dessa Ät.
Det vi ska utnyttja Àr en feature i arrayen - nÀmligen dess index! Med hjÀlp av indexet kan vi skapa unika namn pÄ vÄra uppgifter/knappar!
Vi modifierar koden lite!
javascript
const tasks = [];
const tasklistDiv = document.querySelector('#tasklist');
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task, index) => { // LÀgg till "index" hÀr
htmlCode += `<li>
${task.description}
<button id="done-${index}">Klar</button> // Och id-attribut hÀr
</li>`;
});
tasklistDiv.innerHTML = htmlCode;
addDoneBtnClickEvents();
}
function addDoneBtnClickEvents() {
const doneButtons = document.querySelectorAll('button');
doneButtons.forEach((btn) => {
btn.addEventListener('click', toggleTaskStatus);
});
}
function toggleTaskStatus() {
console.log('Task is done!');
}
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
// Skapa en ny uppgift & lÀgg till i listan
const newTask = {
description: newTaskDescription,
done: false,
};
tasks.push(newTask);
console.table(tasks);
printTasks();
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Om du nu granskar DOM:en nÀr du har lagt till en uppgift, sÄ kommer du se att dessa har unika ID:n pÄ Klar-knapparna.
16. Ta reda pÄ vilken knapp vi klickade pÄ
Nu ska vi ta reda pÄ vilken Klar-knapp det var vi klickade pÄ! Det gör vi sÄhÀr:
javascript
const tasks = [];
const tasklistDiv = document.querySelector('#tasklist');
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task, index) => {
htmlCode += `<li>
${task.description}
<button id="done-${index}">Klar</button>
</li>`;
});
tasklistDiv.innerHTML = htmlCode;
addDoneBtnClickEvents();
}
function addDoneBtnClickEvents() {
const doneButtons = document.querySelectorAll('button');
doneButtons.forEach((btn) => {
btn.addEventListener('click', toggleTaskStatus);
});
}
// Ăndra funktionen nedan
function toggleTaskStatus(evt) { // LĂ€gg till en "event-parameter" i funktionen
const whichDoneBtn = evt.currentTarget.id;
console.log('Task is done:', whichDoneBtn);
}
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
// Skapa en ny uppgift & lÀgg till i listan
const newTask = {
description: newTaskDescription,
done: false,
};
tasks.push(newTask);
console.table(tasks);
printTasks();
}
const createTaskBtn = document.querySelector('#createTaskBtn');
createTaskBtn.addEventListener('click', createNewTask);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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
I funktionen toggleTaskStatus lÀgger vi till en parameter. Den kommer att innehÄlla information om sjÀlva klicket. Vanligt Àr att förkorta eventet till e eller evt. Detta "event" skapas automatiskt och innehÄller info om t.ex. var nÄgonstans pÄ skÀrmen vi klickade, pÄ vad, och en massa annat. Men just nu Àr vi intresserade av VAD vi klickade pÄ.
Det fÄr vi fram via currentTarget, som Àr en referens till HTML-element vi klickade pÄ - knappen i detta fallet.
Och genom att lÀsa av .id, sÄ borde vi i konsolen fÄ ut knappens ID.
Testa om det fungerar! FÄr du ut olika done-0, done-1, osv.?
17. Markera rÀtt uppgift som klar
Bra, nu vet vi vilken uppgiftsknapp vi klickade pÄ. DÄ ska vi "toggla" statusen för den uppgiften.
Vi har ju nu en koppling mellan uppgiftens "plats" i arrayen, och knappens namn. Vi behöver fÄ ut siffran frÄn knappens id. Det kan vi anvÀnda för att markera rÀtt uppgift som klar i arrayen.
Enklast Àr att radera done- frÄn t.ex. done-0. DÄ fÄr vi bara kvar siffran 0, som vi kan anvÀnda för att kolla upp platsen.
Det gör vi sÄhÀr (modda funktionen sÄ att den ser ut som nedan):
javascript
// Ăvrig kodâŠ
function toggleTaskStatus(evt) {
const whichDoneBtn = evt.currentTarget.id;
// Ta fram uppgiftens plats i arrayen (t.ex. 0)
const index = whichDoneBtn.replace('done-', '');
// AnvÀnd siffran (index) frÄn ovan, och markera uppgiftens status som klar
tasks[index].done = true;
console.table(tasks);
}
// Ăvrig kodâŠ1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Nu borde du i konsolen se att uppgiften Àr klar nÀr du klickar pÄ den (Àven om inget hÀnder i DOM).
Vi behöver göra en ny utskrift av vÄra uppgifter med den uppdaterade statusen, och en annan text pÄ knappen!
18. Skriv ut uppgifterna med ny status
Det gör du genom att anropa funktionen printTasks igen!
javascript
// Ăvrig kodâŠ
function toggleTaskStatus(evt) {
const whichDoneBtn = evt.currentTarget.id;
// Ta fram uppgiftens plats i arrayen (t.ex. 0)
const index = whichDoneBtn.replace('done-', '');
// AnvÀnd siffran (index) frÄn ovan, och markera uppgiftens status som klar
tasks[index].done = true;
console.table(tasks);
printTasks();
}
// Ăvrig kodâŠ1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Men vi behöver ocksÄ en visuell indikator att statusen Àndrats! Modifiera funktionen printTasks enl. nedan:
javascript
function printTasks() {
let htmlCode = '<ul>';
// Loopa igenom alla uppgifter och skriv ut dessa
tasks.forEach((task, index) => { // LÀgg till "index" hÀr
if (task.done) {
htmlCode += `<li>
${task.description}
<button id="done-${index}">Ej klar</button>
</li>`;
} else {
htmlCode += `<li>
${task.description}
<button id="done-${index}">Klar</button>
</li>`;
}
});
tasklistDiv.innerHTML = htmlCode;
addDoneBtnClickEvents();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Vi skriver alltsÄ ut olika knapptext beroende pÄ om uppgiften Àr klar, eller inte klar.
Men⊠en sista grej. Det vore kul om vi kunde markera uppgiften igen som ej klar, och det kan vi göra med en liten, liten modifiering av vĂ„r kodâŠ
19. Toggla statusen
I funktionen toggleTaskStatus kan vi Àndra raden enl. nedan:
javascript
function toggleTaskStatus(evt) {
const whichDoneBtn = evt.currentTarget.id;
// Ta fram uppgiftens plats i arrayen (t.ex. 0)
const index = whichDoneBtn.replace('done-', '');
// AnvÀnd siffran (index) frÄn ovan, och markera uppgiftens status som klar
tasks[index].done = !tasks[index].done;
console.table(tasks);
printTasks();
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Det som hÀnder nu Àr att vi sÀger att statusen ska vara MOTSATSEN till nuvarande status.
Dvs. om statusen Ă€r true (klar), sĂ„ blir den motsatsen false (ej klar). Ăr den false, sĂ„ blir den true.
Booleans har en "nifty" funktion att vi kan sÀtta den till dess motsatsvÀrde med hjÀlp av att skriva ett utropstecken framför.
SĂ„ i princip:
javascript
let status = !status;1
Prova att allt funkar som det ska, gÄ och ta en paus, fundera pÄ vad som hÀnde och prova gÀrna att Äterskapa detta en eller tvÄ gÄnger sÄ att du kÀnner dig nÄgorlunda bekvÀm med vad som sker!
(Det Àr en fördel att göra samma uppgift 2-3 gÄnger för du kommer sjÀlv att mÀrka att "jajaja, det dÀr kan jag redan, fy vad trÄkigt att göra det igen")
GĂ„ vidare â
Om du vill utmana dig sjÀlv lite, sÄ skulle du kunna:
- LÀgga till olika CSS-klasser beroende pÄ statusen pÄ uppgiften
- LÀgga till ett fÀlt för deadline/datum
- Sortera uppgifterna beroende pÄ deras status (men dÄ kommer index-principen vi anvÀnde ovan inte att fungera, och du behöver istÀllet skapa unika id:n för uppgifterna). Du kan t.ex. anvÀnda en rÀknare för det, se nedan.
- Skapa en knapp för att radera en uppgift
Ett unikt id (rÀknare)
Skapa en variabel, t.ex. let uniqueId = 0; och lÄt den börja pÄ 0.
Varje gÄng du lÀgger till en uppgift, sÄ plussar du pÄ rÀknaren med 1. PÄ sÄ vis ökar "index"/rÀknaren varje gÄng.
javascript
let uniqueId = 0;
// Ăvrig kodâŠ
function createNewTask() {
const newTaskDescription = document.querySelector('#taskName').value;
const newTask = {
description: newTaskDescription,
done: false,
id: uniqueId,
};
tasks.push(newTask);
console.table(tasks);
printTasks();
uniqueId += 1;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Och i utskriften (printTasks) behöver du, istÀllet för loopens index, byta ut knappens ID mot task.id.