Lekce 8 - OOP diář v JavaScriptu - Ukládání, řazení, seskupování
V minulé lekci, Formát JSON, jsme si představili populární formát JSON.
Implementace
localStorage
v diáři
Konečně tedy můžeme diář upravit tak, aby se data ukládala a
načítala z/do localStorage
. Naše pole zaznamy
třídy Diar
budeme ukládat jednoduše pod klíčem
"zaznamy"
.
Načítání
V konstruktoru diáře tedy místo vytvoření prázdného pole se záznamy
záznamy načteme z localStorage
:
constructor(jazyk = "cs-CZ") { const zaznamyZeStorage = localStorage.getItem("zaznamy"); this.zaznamy = zaznamyZeStorage ? JSON.parse(zaznamyZeStorage) : []; this.jazyk = jazyk; this.nazevInput = document.getElementById("nazev"); this.datumInput = document.getElementById("datum"); this.potvrditButton = document.getElementById("potvrdit"); this.vypisElement = document.getElementById("seznam-ukolu"); this.nastavUdalosti(); }
Do proměnné zaznamyZeStorage
vybereme naše záznamy z
localStorage
. Dále musíme zkontrolovat, pokud nějaké záznamy
uložené vůbec jsou. Pokud ne, proměnná zaznamyZeStorage
nabude
hodnoty null
. Proto zde máme ternární
operátor, díky kterému vlastnosti zaznamy
nastavíme buď
naparsované pole z localStorage
nebo prázdné pole.
Ukládání
Načítání záznamů z localStorage
máme, nyní přidáme i
jejich ukládání při přidání nového záznamu. Záznamy budeme ukládat
jak do pole zaznamy
, tak do storage. Pracovat v celé aplikaci jen
se storage by vyžadovalo neustálé převádění záznamů z objektu na text a
zpět. Proto jej využíváme jen pro načítání na začátku a průběžné
ukládání.
Do metody nastavUdalosti()
přidáme jeden řádek ukládající
záznam i do storage:
nastavUdalosti() { this.potvrditButton.onclick = () => { const zaznam = new Zaznam(this.nazevInput.value, this.datumInput.value); this.zaznamy.push(zaznam); localStorage.setItem("zaznamy", JSON.stringify(this.zaznamy)); // přidaný řádek this.vypisZaznamy(); }; }
Můžeme projekt zkusit spustit, přidat úkoly a znovu načíst stránku. Úkoly v aplikaci již nyní zůstávají a to znamená, že máte svou první reálně použitelnou objektovou aplikaci. Gratuluji!
Výpis záznamů
Celkem snadno jsme si vyřešili náš problém s ukládáním. Pojďme ještě upravit výpis našich záznamů. Bylo by vhodné záznamy seřadit dle data a seskupit záznamy ve stejný den, které vypíšeme pod sebou v jednom bloku.
Řazení
Nejdříve si naimplementujeme metodu na řazení záznamů. K tomu
použijeme metodu sort()
na poli. Ta dokáže pole seřadit
postupným porovnáváním dvojic prvků. Jako parametr přijímá porovnávací
funkci, která definuje jakým způsobem se mají 2 prvky v poli porovnat. Naše
metoda k seřazení záznamů v poli podle data bude ve třídě
Diar
vypadat následovně:
seradZaznamy() { this.zaznamy.sort(function (zaznam1, zaznam2) { return (new Date(zaznam1.datum) - new Date(zaznam2.datum)); }); }
Funkce porovnává data dvou záznamů, která si naparsujeme na datum
pomocí konstruktoru objektu Date
. Ze záznamu samozřejmě
vybereme vlastnost datum
. Porovnání dvou datumů provedeme
jednoduše pomocí operátoru -
, čímž se vrátí jejich rozdíl
v milisekundách. Pokud bude první datum až po druhém, vrátí se záporné
číslo. Pokud budou stejné, vrátí se 0
. Jinak se vrátí
kladné číslo. Právě kladné, záporné nebo nulové číslo metoda
sort()
pro svou práci potřebuje a tím zjistí, zda je datum
větší, menší nebo rovné.
Metodu budeme volat před každým výpisem záznamů:
vypisZaznamy() { this.seradZaznamy(); this.vypisElement.innerHTML = ""; for (const zaznam of this.zaznamy) { this.vypisElement.insertAdjacentHTML("beforeend", `<h3>${zaznam.nazev}</h3>kdy: ${zaznam.datum}<br>splněno: ${zaznam.splneno}`); } }
Záznamy, respektive jejich hodnoty (název, datum) budeme připisovat do
dokumentu pomocí funkce insertAdjacentHTML()
. Jako první parametr
je lokace, kde následující HTML vložíme (druhý parametr). První parametr
má celkem 4 lokace a to:
beforebegin
- před elementafterbegin
- po elementubeforeend
- před koncem elementuafterend
- po elementu
Lépe si to vysvětlit můžeme ještě podle tohoto schématu, kdy
<div>
s třídou seznam-ukolu
je náš
<div>
v aplikaci :
<!-- beforebegin --> <div class="seznam-ukolu"> <!-- afterbegin --> nějaký obsah (zde po vložení prvního záznamu bude onen první záznam) <!-- beforeend (zde vkládáme nové záznamy) --> </div> <!-- afterend -->
Seřazení bychom mohli také volat po přidání záznamu a po jejich načtení, aby se nemuselo volat při každém výpisu. Nevýhodou tohoto řešení by ovšem bylo, že bychom na něj mohli zapomenout při jiné manipulaci se záznamy.
Pokud nyní diář spustíme a máme v localStorage
již
nějaká data, vypíší se nám již seřazená podle data.
Seskupování
Nyní výpis záznamů dokončíme. Budeme tedy vypisovat datum a k tomuto datumu vždy všechny záznamy v daný den. Náš cyklus lehce upravíme:
vypisZaznamy() { this.seradZaznamy(); this.vypisElement.innerHTML = ""; let posledniDatum = null; for (const zaznam of this.zaznamy) { if (zaznam.datum !== posledniDatum) { this.vypisElement.insertAdjacentHTML("beforeend", `<h3>${zaznam.datum}</h3>`); } posledniDatum = zaznam.datum; this.vypisElement.insertAdjacentHTML("beforeend", `<strong>${zaznam.nazev}</strong><br>splněno: ${zaznam.splneno}<hr>`); } }
Do proměnné posledniDatum
přiřadíme vlastnost
datum
z předchozího záznamu. Protože při prvním průběhu
cyklu poslední záznam ještě není, nastavíme proměnnou prvně na
null
. Datum současného záznamu poté vypíšeme jen pokud se
liší od předchozího. Tak se záznamy ve stejný den budou seskupovat. Nyní
máme vypsané hezky úkoly se stejným datem pod sebou a seřazené:
V příští lekci, OOP diář v JavaScriptu - Formátování a mazání záznamů, do našeho objektového diáře v JavaScriptu přidáme několik dalších funkcí.