Lekce 4 - Dokončení kalkulačky v AngularJS

JavaScript Angular Dokončení kalkulačky v AngularJS

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, První aplikace v AngularJS, jsme započali tvorbu jednoduché kalkulačky v javascriptovém frameworku AngularJS. V tomto tutoriálu na ni navážeme a dokončíme její implementaci. Minule jsme tedy dokončili aplikační strukturu a stáhli si potřebné knihovny. Dnes budeme především implementovat v JS, takže bez dalšího otálení jdeme na to! :)

Model

Naši kalkulačku začneme implementovat od jejího modelu tj. od jejích služeb v podání AngularJS.

app/services/cal­culator.servi­ce.js

Řekněme, že naše kalkulačka bude mít 4 základní operace, tj. sčítání, odčítání, násobení a dělení. Tyto operace umístíme do modelu, protože nám vracejí výsledky, tj. naše data. Do souboru calculator.service.js tedy doplníme AngularJS službu, která plní onu roli modelu a vypadá následovně:

'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);
        };
});

Kromě definice služby ve frameworku by zde pro vás nemělo být nic překvapivého. Můžete si ale povšimnout, že jelikož jsem se rozhodl provádět operace v celých číslech, tak chci tuto vlastnost zachovat i u dělení, tudíž výsledek zaokrouhluji na celá čísla. Dále si bystřejší z vás určitě všimli, že není ošetřeno dělení nulou. To však technicky není chyba, protože pro JS toto nekončí chybou, ale číselnou hodnotou "nekonečno" :)

Takže základní operace bychom měli, to však ještě není všechno. Jelikož by model měl být rozšiřitelný a podle MVC bychom při změně modelu nejlépe neměli měnit ani kontroler, ani šablonu, přidáme si ještě jednoduché rozhraní, které nám tyto vlastnosti zajistí. To znamená, že přidáme ještě následující vlastnost a metodu:

...
/**
 * 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;
}
...

První část kódu definuje novou vlastnost operations, která obsahuje názvy operací a jejich popisky. Druhá část kódu definuje metodu, která podle textového řetězce s názvem operace zavolá danou metodu kalkulačky. Protože název operace bude shodný s názvem metody, můžeme podle něj metodu vybrat jako this[operation], kdy v operation je např. hodnota "add", což spustí metodu add(). Opět nic, co vás při znalosti JS překvapí. Kdo náhodou neví, tak takto se v JS definují objektové vlastnosti a provádí reflexe :)

Kontroler

Pokračovat budeme implementací kontroleru v rámci AngularJS.

app/controller­s/calculator.con­troller.js

Vytvoříme jej tedy v souboru calculator.controller.js a vypadat bude následovně:

'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);
        };
});

Zde bych se již na chvíli zastavil. Nejdříve si povšimněte definice kontroleru v rámci frameworku, kde je také vidět DI (Dependency Injection, která nám umožňuje předávat služby napříč naší aplikací). Ta v AngularJS funguje opravdu skvěle, když v kontroleru potřebujeme používat nějaký model, jednoduše si jej necháme frameworkem předat. Stačí napsat název služby jako parametr a je hotovo, žádná další konfigurace není třeba.

Dále se zde definují proměnné, které budou fungovat v šabloně pro předání hodnot. Pokud tedy deklarujeme proměnnou lokálně, bude k dispozici pouze pro kontroler jako takový. Pokud ji ale uděláme přímo na objektu, bude dostupná i v šabloně. To samé platí i u metod, které poté můžeme volat jako akce z šablon.

U proměnných tento princip navíc ještě znamená, že díky obousměrnému bindování (propisování hodnot mezi HTML šablonou a JS proměnnými), což je jedna z hlavním předností AngularJS frameworku, zde vlastně definujeme počáteční hodnoty v šabloně. Ostatně to za chvíli uvidíte :)

Šablona (View)

Na závěr si doplníme šablonu pro náš kontroler, což je vlastně mix hlavně HTML a AngularJS kódu.

index.html

Šablonu pro jednoduchost vepíšeme přímo do souboru index.html a to dovnitř připraveného "wrapperu". Ovšem nutno podotknout, že standardně bývají šablony odděleny v souborech 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ávěr si pojďme tento kód trochu rozebrat. Jeho základ tvoří HTML formulář, to by mělo být jasné. Dále je vidět definice kontroleru pomocí ng-controller, která v podstatě říká, že tento blok HTML kódu se mapuje jako jeho šablona a má tím pádem přístup k jeho datům a akcím. Zároveň je zde pro něj zaveden alias "calculator".

Posléze se tedy mapuje odeslání formuláře (submit) na akci kontroleru "calculate" pomocí ng-submit a jednotlivé proměnné tohoto kontroleru jako model pro formulář pomocí ng-model. Tím se prováže předávání dat pomocí již zmíněného bindování.

Další věcí je generování možností pro HTML <select> pomocí ng-options, které je vytváří přímo z předaných hodnot kontroleru.

Na konci je poté vidět zobrazení výsledku pomocí frameworkového zápisu {{...}}, pokud je definován (ng-show), který se díky Angularu dynamicky mění v závislosti na aktuálním výpočtu. Důležité je zde také označení ng-cloak, které daný element schová pomocí CSS, dokud není JS načtený, aby mohl převzít kontrolu. Toto CSS jsme si definovali už v minulé lekci.

A tím je naše práce na šabloně i na celém projektu hotová. Pokud se teď podíváte na URL projektu, měli by jste vidět funkční kalkulačku a můžete na ní vyzkoušet všechny chytáky, které vás napadnou :)

Pokud vám není cokoli jasné, stáhněte si projekt z přílohy a projeďte si ho. Kódu v aplikaci tolik nemáme, po chvíli byste se v principu měli zorientovat.

To je pro tuto lekci opravdu vše, ale nebojte, příště začneme úplně novou pořádnou aplikaci v AngularJS. A co to bude, to se nechte překvapit ;)


 

Stáhnout

Staženo 49x (15.24 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Jindřich Máca
Avatar
Jak se ti líbí článek?
1 hlasů
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. :-)
Miniatura
Předchozí článek
První aplikace v AngularJS
Miniatura
Všechny články v sekci
Angular
Aktivity (2)

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!