Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 30% výuky zdarma!
Discount week - Prosinec

Lekce 10 - Dokončení objektového diáře v JavaScriptu

V minulé lekci, OOP diář v JavaScriptu - Formátování a mazání záznamů, jsme do našeho objektového diáře v JavaScriptu přidali několik dalších funkcí.

Dnes do našeho diáře přidáme tlačítko na splnění úkolu, validaci data a jednoduché CSS styly :)

Změna splněnosti záznamů

Poslední tlačítko, které nám chybí, je tlačítko na splnění úkolu.

Parametrizace

Protože tlačítko na splnění úkolu bude vypadat a fungovat velmi podobně jako mazací tlačítko, nebudeme do aplikace zbytečně vkládat duplicitní kód, ale upravíme ten stávající. Vytvoříme si pomocnou metodu na vložení tlačítka k úkolu:

_pridejTlacitko(titulek, callback) {
    const button = document.createElement("button");
    button.onclick = callback;
    button.innerText = titulek;
    this.vypisElement.appendChild(button);
}

Metoda _pridejTlacitko() dělá přesně to, co jsme měli u přidání mazacího tlačítka. Titulek a obslužnou metodu tlačítka ovšem nastavuje z parametru, takže ji můžeme použít pro vložení různých tlačítek s různými titulky a funkcemi.

Místo veškerého kódu pro mazací tlačítko nyní stačí do metody vypisZaznamy() vložit jen:

this._pridejTlacitko("Smazat", () => {
    if (confirm("Opravdu si přejete odstranit úkol?")) {
        this.zaznamy = this.zaznamy.filter(z => z !== zaznam); // Ponechá vše co není rovné proměnné zaznam
        this.ulozZaznamy();
        this.vypisZaznamy();
    }
});

Pomocnou metodu jsme si vytvořili záměrně až nyní a ne již před přidáním prvního tlačítka. To abychom si ukázali, jak se v praxi řeší situace, když potřebujete do aplikace vložit nějaký velmi podobný kód. Kód stávající vyčleníte do pomocné metody a parametrizujete jej. Prezence duplicitního kódu porušuje princip DRY, jedno z nejdůležitějších pravidel kvalitního objektového návrhu.

Privátní metody

Všimněte si, že název metody začíná na podtržítko. Pomocné metody, které by na naší třídě neměl zvenčí nikdo volat, by se měly ideálně skrýt. JavaScript v současné době bohužel neumožňuje metody rozumně zapouzdřit. Dále v kurzu si sice ukážeme, že je to možné, ale jen pomocí hacků, což kód ve výsledu znepřehlední. Označení privátních vlastností a metod pomocí podtržítka je poměrně dobrý návyk a dělá se tak často i v ostatních jazycích, které nepodporují modifikátory přístupu.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Aby byl náš kód opravdu dobře napsaný, označme si podtržítkem i metodu _nastavUdalosti(). Rovněž se jedná jen o pomocnou funkcionalitu, která by zvenčí neměla být volána.

_nastavUdalosti() {
    // ...
}

Nezapomeňte přejmenovat i volání metody v konstruktoru:

constructor(jazyk = "cs-CZ") {
    // ...
    this._nastavUdalosti();
}

Tlačítko na splnění záznamu

Po malé odbočce se vraťme zpět k novému tlačítku. To nyní vložíme pomocí připravené metody _pridejTlacitko():

this._pridejTlacitko("Označit jako " + (zaznam.splneno ? "nesplněný" : "splněný"), () => {
    zaznam.splneno = !zaznam.splneno;
    this.ulozZaznamy();
    this.vypisZaznamy();
});

Výsledek si můžete vyzkoušet :)

Ošetření vstupu

Máme tedy plně funkční diář s ukládáním do localStorage. Jediné, co nám ještě chybí, je ošetřit vstup, protože pokud uživatel nezadá datum, bude se nám vypisovat jako "Invalid Date". Upravíme si tedy metodu _nastavUdalosti() a uděláme zde jednoduchou validaci. Díky tomu, že <input type="date"> vrací value jako prázdný string, když je datum neúplné, není těžké uživatele na tento stav upozornit:

_nastavUdalosti() {
    this.potvrditButton.onclick = () => { // this zůstane nyní stále this
        if (this.datumInput.value !== "") {
            const zaznam = new Zaznam(this.nazevInput.value, this.datumInput.value);
            this.zaznamy.push(zaznam);
            this.ulozZaznamy();
            this.vypisZaznamy();
        } else
            alert("Musíte vyplnit datum!");
    };
}

Takže pokud nebude zadáno datum správně, upozorníme uživatele funkcí alert(), že ho má zadat správně, jinak nový záznam uložíme.

Design

Nyní již zbývá jen nějaký design, který si rychle prolétneme a jen minimálně upravíme v JS. Vytvoříme si v projektu složku css/, a nový soubor styly.css. Jeho obsah bude následující:

* {
    font-family: Segoe UI Light, "Calibri Light", sans-serif;
}

button {
    padding: 10px 16px;
    font-weight: 600;
    background: #2792e0;
    color: #fff;
    border: none;
    cursor: pointer;
    transition: .5s;
}

button:hover {
    background: #2954c2;
}

button:active {
    background: #204199;
}

input {
    min-width: 250px;
    padding: 8px;
    border: 1px solid #909090;
    height: 20px;
}

button, input {
    margin-top: 1rem;
    outline: none;
}

.ukol {
    width: 75%;
    padding: 2rem;
    margin: 1rem auto;
    border: 1px solid #c5c5c5;
    box-shadow: 2px 2px 4px #b1b1b1;
}

Styly nalinkujeme v index.html:

<link href="css/styly.css" rel="stylesheet">

A nyní jen lehce upravíme výpis každého záznamu:

this.vypisElement.innerHTML += `<h4>${zaznam.nazev}</h4>
    <br>úkol ${!zaznam.splneno ? "ne" : ""}splněn`;
    // ...
this.vypisElement.innerHtml = `<div class="ukol">` + this.vypisElement.innerHtml  + `</div>`;

Výsledek:

Your page
localhost

Tak a je hotovo! :) Máme tedy celkem pěkně vypadající diář, který ukládá data a lze jej reálně používat :) Pokud jste měli s čímkoli problém, pod článkem si můžete stáhnout kompletní zdrojové kódy a najít si chybu.

V příští lekci, AJAX v JavaScriptu - Základní dotazy, na nás čeká populární technologie AJAX!


 

Stáhnout

Staženo 324x (4.22 kB)

 

Předchozí článek
OOP diář v JavaScriptu - Formátování a mazání záznamů
Všechny články v sekci
Objektově orientované programování v JavaScriptu
Článek pro vás napsal Šimon Raichl
Avatar
Jak se ti líbí článek?
5 hlasů
Autor se věnuje hlavně tvorbě všemožných věcí v JS
Aktivity (5)

 

 

Komentáře
Zobrazit starší komentáře (6)

Avatar
Patrik Pastor:14.4.2019 9:28

cau, napadlo me pridat jeste tlacitko pro vymazani celeho diar (v pripade, ze byste meli spoustu poloezek, nebo proste chteli smaznout historii), tak jsem v html vytvoril button element navazal ho v kontruktoru a do metody nastavUdalosti, pripsal tuto metodu:

this.vycistit­Button.onclick = () =>{
if (alert("Opravdu si prejete vycistit Diar?")){
localStorage.cle­ar();
this.ulozZaznamy();
this.vypisZaz­namy();
}
}

Ovsem po kliknuti nic. Alert vyskoci, ale po "ok" jsou zaznamy porad k nalezeni, nenapada nekoho proc to nefunguje? (na netu jsem hledat funkci localStorage.cle­ar() a nemela by mit zadny parametr, takze myslim ze tam chyba neni, potom me ale nenapada proc to nefunguje.

 
Odpovědět
14.4.2019 9:28
Avatar
Patrik Pastor:14.4.2019 9:46

zkusil jsem a lze to mazat z prostredka, nicmene to rozbilo tim DIVem cele css. Jde o to ze ted, pokud mas k jednomu datu vice zaznamu, pak tlacitka jednotlivych zaznamu jsou NAKONCI tohoto divu. Jinymi slovy tlacitka uz nejsou u kazde polozky jednotlive, ale nevzhledne rozhazeny v dusledku pridani divu. Jak jsi to teda vyresil s tlacitky, aby zustaly u kazde polozky?

 
Odpovědět
14.4.2019 9:46
Avatar
x.listo
Člen
Avatar
Odpovídá na Patrik Pastor
x.listo:14.4.2019 14:03

Výborně.
To jsem přehlédl. Řešení může být přidání dalšího parametru do _pridejTlacitko, který bude reprezentovat konkrétní úkol.

_pridejTlacitko(titulek, callback, ukol) {
            const button = document.createElement("button");
            button.onclick = callback;
            button.innerText = titulek;
            ukol.appendChild(button);
    }

Potom už stačí jen doplnit požadovaný element jako parametr do obou volání.

this._pridejTlacitko("Smazat", () => {
                            if (confirm("Opravdu si přejete odstranit úkol?")) {
                                    this.zaznamy = this.zaznamy.filter(z => z !== zaznam); // Ponechá vše co není rovné proměnné zaznam
                                    this.ulozZaznamy();
                                    this.vypisZaznamy();
                            }
                    }, ukol);

this._pridejTlacitko("Označit jako " + (zaznam.splneno ? "nesplněný" : "splněný"), () => {
                            zaznam.splneno = !zaznam.splneno;
                            this.ulozZaznamy();
                            this.vypisZaznamy();
                    }, ukol);
 
Odpovědět
14.4.2019 14:03
Avatar
Odpovídá na x.listo
Patrik Pastor:14.4.2019 17:43

Diky, ted uz je vsechno vporadku (skoda ze sem na to sam neprisel, ale tak delam to poprve), proto jsem si chtel pridat prave tlacitko pro odstraneni celeho zaznamu (pri vytvareni jsem omylem naklikal jeden zaznam hodnekrat, a kdyz to konecne najelo, mel jsem tam ukoly uplne vsechny). Metoda pro tlacitko byla "localStorage­.clear()" - jak jsem na sel na stackoverflow, ale stejne mi nejede, nevis proc?

_nastavUdalosti(){
// => znaci zmenu klicoveho slova this na puvodni kontext (tedy "this" plati pro klasu "Diar")
this.potvrdit­Button.onclick = () => {
if (this.datumIn­put.value !== ''){
const zaznam = new Zaznam(this.na­zevInput.valu­e, this.datumInput­.value);
this.zaznamy.push(zaz­nam);
this.ulozZaznamy();
this.vypisZaz­namy();
} else {
alert('Musite vyplnit datum');
}
};
// TATO METODA MA VYCISTIT CELY DIAR

this.vycistit­Button.onclick = () =>{
if (alert("Opravdu si prejete vycistit Diar?")){
window.localSto­rage.clear();
this.ulozZaznamy();
this.vypisZaz­namy();
}
}
}

vycistitButton je navazane tacitko, ktere jsem v html napsal pod potvrdit:
<div>
<button id='potvrdit'>U­ložit úkol</button>
<button id='vycistit'>Vy­cistit diar</button>
</div>

 
Odpovědět
14.4.2019 17:43
Avatar
x.listo
Člen
Avatar
Odpovídá na Patrik Pastor
x.listo:15.4.2019 12:16

Dvě věci byly na čistícím tlačítku špatně. Alert nahradit confirm, aby byla návratová hodnota true nebo false pro rozhodnutí podmínky.

confirm("Opravdu si prejete vycistit Diar?")

Z localstorage se sice data odstranila, ale zůstávala ještě uložena v poli this.zaznamy. Takže řádek s this.ulozZaznamy() je zbytečný. Nahradil jsem jej vymazáním pole this.zaznamy = [];

// TATO METODA MA VYCISTIT CELY DIAR

        this.vycistitButton.onclick = () => {
        if (confirm("Opravdu si prejete vycistit Diar?")){
            window.localStorage.clear();
            this.zaznamy = [];
            this.vypisZaznamy();
            };
        };
Editováno 15.4.2019 12:19
 
Odpovědět
15.4.2019 12:16
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Lenka Mackova:18.10.2019 21:16

nefunguji tlacitka pro smazani, nekde je v tom kodu chyba. No jdu hledat nejaky jednoduchy reseni jak to zpravit aby mi to fungovalo.:-))

 
Odpovědět
18.10.2019 21:16
Avatar
Lenka Mackova:18.10.2019 21:45

this._pridejTla­citko("Smazat", () => {
if (confirm("Opravdu si přejete odstranit úkol?")) {
this.zaznamy = this.zaznamy.fil­ter(z => z !== zaznam); // Ponechá vše co není rovné proměnné zaznam

this.ulozZaznamy();
this.vypisZaz­namy();
}
delete zaznamy.regex;
});

Tak se mi povedlo ze aspon posledni polozka v seznamu ukolu se vymaze pomoci delete zaznamy.regex; ale ted premyslim jak to aplikovat na vsechny. Pokud nekdo vi muze mi poradit.

 
Odpovědět
18.10.2019 21:45
Avatar
Lenka Mackova:18.10.2019 22:12

no tak zaclo fungovat, problem mam s tim, ze se mi tlacitka radi vsechny dole vedle sebe, takze mam seznam ukolu a tlacitka na stridacku v jednom radku dole pod tim.

 
Odpovědět
18.10.2019 22:12
Avatar
Jakub Podskalský:28.10.2019 18:58

Děkuji za skvělý program. :) Sice je ten kód v minulé a v této lekci pro funkčnost potřeba trochu přepsat, ale jinak z toho vznikne zajímavý výsledek. :P
Přidal jsem ještě tlačítko na smazání všech záznamů. V HTML ho vložil pod button potvrzení. Pak vytvořil v konstruktoru proměnnou a v metodě nastavUdalosti vložil tento kód:

this.smazatVseButton.onclick = () => {
            if (confirm("Opravdu si přeješ smazat všechy záznamy?")) {
                this.zaznamy = [];
                this.ulozZaznamy();
                this.vypisZaznamy();
            }
        };
 
Odpovědět
28.10.2019 18:58
Avatar
Pavel Blahuš:11. února 0:39

ahoj
stahnul jsem zaverecny diar.zip. po spusteni nefunguje, zobrazi se jen:
Diář
xx

xx
Potvrdit úkol (zadam, potvrdim ) ... a nic

kde je problém???
dik

 
Odpovědět
11. února 0:39
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 16. Zobrazit vše