Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

4. diel - Dokončenie kalkulačky v AngularJS

V minulej lekcii, Prvé aplikácie v AngularJS , sme začali tvorbu jednoduchej kalkulačky v javascriptové frameworku AngularJS. V tomto tutoriálu na ňu nadviažeme a dokončíme jej implementáciu. Minule sme teda dokončili aplikačné štruktúru a stiahli si potrebné knižnice. Dnes budeme predovšetkým implementovať v JS, takže bez ďalšieho otáľania ideme na to! :)

Model

Naši kalkulačku začneme implementovať od jej modelu tj. Od jej služieb v podaní AngularJS.

App / services / calculator.ser­vice.js

Povedzme, že naša kalkulačka bude mať 4 základné operácie, tj. Sčítanie, odčítanie, násobenie a delenie. Tieto operácie umiestnime do modelu, pretože nám vracajú výsledky, tj. Naše dáta. Do súboru calculator.service.js teda doplníme AngularJS službu, ktorá plní onú úlohu modelu a vyzerá nasledovne:

'use strict';

/**
 * Model operací kalkulačky.
 */
app.service('Calculator', function () {
    /**
     * Sečte daná čísla a vrátí výsledek.
     * @param {int} x první číslo
     * @param {int} y druhé číslo
     * @return {int} výsledek sčítání
     */
    this.add = function (x, y) {
        return x + y;
    };

    /**
     * Odečte druhé číslo od prvního a vrátí výsledek.
     * @param {int} x první číslo
     * @param {int} y druhé číslo
     * @return {int} výsledek odčítání
     */
    this.subtract = function (x, y) {
        return x - y;
    };

    /**
     * Vynásobí daná čísla a vrátí výsledek.
     * @param {int} x první číslo
     * @param {int} y druhé číslo
     * @return {int} výsledek násobení
     */
    this.multiply = function multiply(x, y) {
        return x * y;
    };

    /**
     * Vydělí první číslo druhým bezezbytku a vrátí výsledek.
     * @param {int} x první číslo
     * @param {int} y druhé číslo
     * @return {int} výsledek dělení beze zbytku
     */
    this.divide = function (x, y) {
        return Math.round(x / y);
    };
});

Okrem pojmu služby vo frameworku by tu pre vás nemalo byť nič prekvapujúce. Môžete si však všimnúť, že keďže som sa rozhodol vykonávať operácie v celých číslach, tak chcem túto vlastnosť zachovať aj u delenie, teda výsledok zaokrúhľuje na celé čísla. Ďalej si bystrejší z vás určite všimli, že nie je ošetrené delenie nulou. To však technicky nie je chyba, pretože pre JS toto nekončí chybou, ale číselnou hodnotou "nekonečno" :)

Takže základné operácie by sme mali, to však ešte nie je všetko. Keďže by model mal byť rozšíriteľný a podľa MVC by sme pri zmene modelu najlepšie nemali meniť ani kontrolér, ani šablónu, pridáme si ešte jednoduché rozhranie, ktoré nám tieto vlastnosti zaistí. To znamená, že pridáme ešte nasledujúce vlastnosť a metódu:

...
/**
 * Definice pole konstant pro operace kalkulačky.
 * @type {String[]}
 */
Object.defineProperty(this, 'operations', {
    value: {
        add: 'Sčítání',
        subtract: 'Odčítání',
        multiply: 'Násobení',
        divide: 'Dělení beze zbytku'
    },
    enumerable: true
});
...
/**
 * Zavolá zadanou operaci a vrátí její výsledek.
 * @param {string} operation zadaná operace
 * @param {int} x            první číslo pro operaci
 * @param {int} y            druhé číslo pro operaci
 * @return {int|null} výsledek operace nebo null, pokud zadaná operace neexistuje
 */
this.calculate = function (operation, x, y) {
    if (this.hasOwnProperty(operation))
        return this[operation](x, y);
    else return null;
}
...

Prvá časť kódu definuje novú vlastnosť operations, ktorá obsahuje názvy operácií a ich popisky. Druhá časť kódu definuje metódu, ktorá podľa textového reťazca s názvom operácie zavolá danú metódu kalkulačky. Pretože názov operácia bude zhodný s názvom metódy, môžeme podľa neho metódu vybrať ako this[operation], kedy v operation je napr. Hodnota "add", čo spustí metódu add(). Opäť nič, čo vás pri znalosti JS prekvapí. Kto náhodou nevie, tak takto sa v JS definujú objektovej vlastnosti a vykonáva reflexie :)

Kontrolér

Pokračovať budeme implementáciou kontroleru v rámci AngularJS.

App / controllers / calculator.con­troller.js

Vytvoríme ho teda v súbore calculator.controller.js a vyzerať bude nasledovne:

'use strict';

/**
 * Kontroler kalkulačky.
 * @param {Object} Calculator model operací kalkulačky předaný pomocí DI
 */
app.controller('CalculatorController', function (Calculator) {
    // Počáteční nastavení hodnot.
    this.x = 0; // První číslo.
    this.y = 0; // Druhé číslo.
    this.operations = Calculator.operations; // Předání výběru operací kalkulačky.
    this.operation = Object.keys(this.operations)[0]; // Výchozí operace kalkulačky (první v seznamu.)
    this.result = null; // Výsledek výpočtu.
    // Definice metod.
    /**
     * Metoda vykonaná při odeslání formuláře kalkulačky, která zpracuje odeslané hodnoty.
     */
    this.calculate = function () {
        this.result = Calculator.calculate(this.operation, this.x, this.y);
    };
});

Tu by som sa už na chvíľu zastavil. Najskôr si všimnite definície kontroleru v rámci frameworku, kde je tiež vidieť DI ( Dependency Injection, ktorá nám umožňuje odovzdávať služby naprieč našou aplikáciou). Tá v AngularJS funguje naozaj skvele, keď v kontroleru potrebujeme používať nejaký model, jednoducho si ho necháme frameworkom odovzdať. Stačí napísať názov služby ako parameter a je hotovo, žiadna ďalšia konfigurácia nie je treba.

Ďalej sa tu definujú premenné, ktoré budú fungovať v šablóne pre odovzdanie hodnôt. Ak teda deklarujeme premennú lokálne, bude k dispozícii len pre kontrolér ako taký. Pokiaľ ju ale urobíme priamo na objekte, bude dostupná aj v šablóne. To isté platí aj u metód, ktoré potom môžeme volať ako akcie z šablón.

U premenných tento princíp navyše ešte znamená, že vďaka obojsmernému bindovanie (prepisovanie hodnôt medzi HTML šablónou a JS premennými), čo je jedna z hlavným predností AngularJS frameworku, tu vlastne definujeme počiatočnej hodnoty v šablóne. Ostatne to za chvíľu uvidíte :)

Šablóna (View)

Na záver si doplníme šablónu pre náš kontrolér, čo je vlastne mix hlavne HTML a AngularJS kódu.

Index.html

Šablónu pre jednoduchosť vpíšeme priamo do súboru index.html a to dovnútra pripraveného "wrapper". Avšak treba podotknúť, že štandardne bývajú šablóny oddelené v súboroch zvlášť.

...
<!-- HTML + AngularJS kód aplikace, především pak formulář kalkulačky. -->
<div id="wrapper" ng-controller="CalculatorController as calculator">
    <h1>Kalkulačka v AngularJS</h1>
    <form ng-submit="calculator.calculate()">
        <label for="x">
            První číslo:
            <input id="x" type="number" required ng-model="calculator.x">
        </label>
        <label for="y">
            Druhé číslo:
            <input id="y" type="number" required ng-model="calculator.y">
        </label>
        <label for="operation">
            Operace:
            <select id="operation" required ng-model="calculator.operation"
                    ng-options="key as value for (key , value) in calculator.operations">
            </select>
        </label>
        <input type="submit" value="Spočítej">
    </form>
    <div id="result" ng-cloak ng-show="calculator.result">Výsledek je: {{calculator.result}}</div>
</div>

...

Na záver si poďme tento kód trochu rozobrať. Jeho základ tvorí HTML formulár, to by malo byť jasné. Ďalej je vidieť definícia kontroleru pomocou ng-controller, ktorá v podstate hovorí, že tento blok HTML kódu sa mapuje ako jeho šablóna a má tým pádom prístup k jeho dátam a akciám. Zároveň je tu pre neho zavedený alias "calculator".

Neskôr sa teda mapuje odoslaní formulára (submit) na akciu kontroléra "calculate" pomocou ng-submit a jednotlivé ukazovatele tohto kontroleru ako model pre formulár pomocou ng-model. Tým sa previaže predávanie dát pomocou už spomínaného bindovanie.

Ďalšou vecou je generovanie možností pre HTML <select> pomocou ng-options, ktoré ich vytvára priamo z odovzdaných hodnôt kontroleru.

Na konci je potom vidieť zobrazenie výsledku pomocou frameworkového zápisu {{...}}, ak je definovaný (ng-show), ktorý sa vďaka ANGULAR dynamicky mení v závislosti na aktuálnom výpočtu. Dôležité je tu tiež označenie ng-cloak, ktoré daný element schová pomocou CSS, dokiaľ nie je JS načítaný, aby mohol prevziať kontrolu. Toto CSS sme si definovali už v minulej lekcii.

A tým je naša práca na šablóne aj na celom projekte hotová. Ak sa teraz pozriete na URL projektu, mali by ste vidieť funkčné kalkulačku a môžete na nej vyskúšať všetky chytáky, ktoré vás napadnú :)

Ak vám nie je čokoľvek jasné, stiahnite si projekt z prílohy a prejdite si ho. Kódu v aplikácii toľko nemáme, po chvíli by ste sa v princípe mali zorientovať.

To je pre túto lekciu naozaj všetko, ale nebojte, nabudúce začneme úplne novú poriadnu aplikáciu v AngularJS. A čo to bude, to sa nechajte prekvapiť ;)


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 91x (15.24 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript

 

Predchádzajúci článok
Prvé aplikácie v AngularJS
Všetky články v sekcii
AngularJS
Preskočiť článok
(neodporúčame)
Jednoduchý redakčný systém v AngularJS - Štruktúra projektu
Článok pre vás napísal Jindřich Máca
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje převážně webovým technologiím, ale má velkou zálibu ve všem vědeckém, nejen ze světa IT. :-)
Aktivity