1/7 - SPA, AngularJS, Bootstrap

 Ez az gyakorlat arról fog szólni, hogyan építs fel egy Single-Page-Application-t azaz egy olyan webalkalmazást, amely "egyetlen oldal"-ból áll. Ez az egyetlen oldal az index.html, de ez ne tévesszen meg téged. Ez csupán azt jelenti, hogy a böngésződ nem fog a szerveren más oldalakat lekérni, mint ahogy azt a portfolio alkalmazásban láttuk (localhost:8080/works.html, localhost:8080/about.html), hanem ezek az oldalak dinamikusan fognak betöltődni, amikor a kliensen gombokat nyomkodsz. A modern webalkalmazások még a böngészőben lévő url-t is változtatják annak megfelelően, hogy épp milyen "oldalon" tartózkodsz (localhost:8080/works, localhost:8080/about, html nélkül). 

Mi azonban egyelőre megelégszünk egyetlen oldallal. A portfolio alkalmazásunkat fogjuk újragondolni, és ehhez egy javascript framework-öt AngulaJS-t fogunk használni. 

Először is hozzunk létre egy új könyvtárat a gépen, másoljuk bele a porfolio app-ból a package.json, start.js és a .gitignore fájlokat, majd Ctrl+Shift+ö-vel nyissunk egy új terminál ablakot VS Code-ban miután megnyitottuk a könyvtárat, és adjuk ki az "npm i" parancsot. Ezután hozzunk létre egy public mappát, és adjunk hozzá egy index.html-t. Alternatívaként töltsük le innen a kiindulóprojektet (utána pedig npm i a terminálba):

https://github.com/czimerk/web7_init

Az AngularJS egy olyan javascript library amivel dinamikusan megjelenő tartalmat tudunk létrehozni. egy böngészőben. Normál esetben javascriptet használva minden html elem tartalmát valamilyen lekérdezéssel és tartalom cseréléssel kéne feltöltenünk (mint a 2. gyakorlaton, amikor az innerHTML property-t állítottuk be). Ezzel szemben az AngularJS úgy működik, hogy van egy html oldal, és ebben {} jelek között meg van adva egy változó neve, ahová egy ún model objektum (javascript változó) van bekötve. Ezt hívják adatkötésnek (binding).



A library azt csinálja, hogy egy digest cycle (feldolgozási ciklus) folyamat révén periodikusan ellenőrzi a változók értékét, és frissíti a tartalmakat.

Nézzünk egy gyakorlati példát. Menjünk fel az https://angularjs.org/ -ra és görgessünk le az első kódpéldához. 

  • Másoljuk ki az <script> -el kezdődő sort, és tegyük bele a <head>szekcióba
  • Másoljuk ki a <body> tartalmát, és tegyük be a saját dokumentumunk <body> részébe
  • írjuk át a <body> -t <body ng-app> -ra
A végleges kód így nézki.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.0/angular.min.js">
    </script>
</head>
<body ng-app>
    <div>
        <label>Name:</label>
        <input type="text" ng-model="yourName" placeholder="Enter a name here">
        <hr>
        <h1>Hello {{yourName}}!</h1>
      </div>
</body>
</html>

Nyomjuk meg az npm startot, vagy ha az alkalmazásunk már fut, akkor Ctrl + F5-tel frissítsük be. Bármit írunk a fenti mezőbe, az meg fog jelenni az alsó részben a Hello után. Ez azért lehetséges, mert az AngularJS két irányú (adat) kötést tesz lehetővé, ami azt jelenti, hogy nem csak a <h1>-be bekötött érték jelenik meg (JS->HTML irány), hanem az input mezőbe bekötött adatmodel is befrissül (HTML -> JS).

Miután megbizonyosodtunk róla, hogy működik az angularJS kezdjük el létrehozni a navigációt, az oldalunkhoz. Ehhez egy Bootstrap-et fogunk használni. Ez egy elég populáris eszköztár reszponzív (minden képernyőn jól kinéző) UI készítéséhez.


A megadott CDN linkeket másoljuk be a <head> szekcióba., majd innen


másoljuk be az első kódpéldát a <body ng-app> tag alá.

<body ng-app>
    <div>
        <nav class="navbar navbar-default">
            <div class="container-fluid">
                <div class="navbar-header">
                    <a class="navbar-brand" href="#">WebSiteName</a>
                </div>
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Home</a></li>
                    <li><a href="#">Page 1</a></li>
                    <li><a href="#">Page 2</a></li>
                    <li><a href="#">Page 3</a></li>
                </ul>
            </div>
        </nav>
    </div>
...

Ebből látható, hogy a bootstrap css osztályokkal operál. Most pedig frissítsük az oldalunkat Ctrl+F5-tel.


Ahhoz hogy az oldal tartalma szebben nézzen ki, még adjuk hozzá ezt a class-t. 


Frissítsük be az oldalt, majd nyomjunk a böngészőben F12-t. Válasszuk ki a responsive nézetet, és kezdjük el beljebb húzni a jobb oldali sávot. Ezzel szimuláljuk hogyan nézne ki az oldal egy olyan eszközön, aminek limitált a kijelző szélessége. Láthatod, hogy a navigációs sáv egy sorból átrendeződik egy oszlopba.



Ha most rámész az inspect element-re, akkor tetszőleges elemet megvizsgálhatsz. Például az előbb említett container-fluid beállítja az adott elmere az oldalsó margin-okat és padding-et. 



Ha a Computed fülre váltasz akkor ott láthatod, mit is takar a margin, border, és a padding.


Még egy dolog feltűnhet. Amikor hozzáadtuk a bootrsrap-et nem vettük figyelembe, hogy a javascript library-jének szüksége van egy másik library-re a jQuery-re.


Adjuk hát hozzá ezt is a header-be a bootsrap elé.

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
A favicon-os hibával egyelőre nem kell törődnünk, de ha nagyon zavar, adjunk hozzá egy üres fájlt favicon.ico néven a public folderhez (engem nagyon zavart...).

A célunk, hogy a navigációs gombok működjenek is. Ehhez írjuk át a navbar-nav osztállyal ellátott elemeket így.

<ul class="nav navbar-nav">
    <li ng-click="setActivePage('home')" ng-class="{'active': isActive('home')}">
        <a href="#">Home</a>
    </li>
    <li ng-click="setActivePage('works')" ng-class="{'active': isActive('works')}">
        <a href="#">Works</a>
    </li>
    <li ng-click="setActivePage('about')" ng-class="{'active': isActive('about')}">
        <a href="#">About</a>
    </li>
    <li ng-click="setActivePage('tutorials')" ng-class="{'active': isActive('tutorials')}">
        <a href="#">Tutorials</a>
    </li>
</ul>

Az ng-click egy AngularJS direktíva (A direktívák olyan kiegészítések a HTML elemekhez, amelyek további funkciók elérését teszik lehetővé a standard funkciók felett, mint például az ng-app), ami arra szolgál, hogy egy javascript-ben megadott függvényt futtasson le, amikor az elemre kattintanak. Bemenő paraméterként szöveget/string-et adtunk meg, hogy jelezzük, éppen melyik elemre kattintottak.

Az ng-class egy CSS osztályt ad hozzá az elemhez attól függően, hogy az utána következő kifejezés igaz-e. Esetünkben egy függvényt fogunk meghívni.

Hozzunk most létre egy main.js fájlt a public mappa alá. Ennek tartalma legyen

var app = angular.module('myApp', []);

app.controller('mainController'function ($scope) {

    var activePage = 'home';

    $scope.isActive = function (page) {
        return activePage === page;
    }

    $scope.setActivePage = function (page) {
        activePage = page;
    }
});

Ez a kód hozza létre az angular alkalmazásunkat, melynek neve myApp. Ezután hozzáadjuk az első controllerünket. A controller szerepe, hogy tárolja az adatmodelleket, illetve, azokat a függvényeket, amelyeket a HTML-fájlból szeretnénk meghívni. Mint fent láttuk, ebből 2 db van:
  • isActive: megmondja, hogy az adott elem aktív e
  • setActivePage: click hatására beállítja az aktív oldalt
Az aktív oldal változóját maga a controller tárolja az activePage változóban.

Ezután már csak a controller-t, és az alkalmazást kell megadni az index.html fájlban

<body ng-app="myApp" ng-controller="mainController">

valamint behivatkozni a main.js fájlt a body záró tag-je elé.




Ha most frissítjük az oldalunkat, akkor bármelyik menüpontot választjuk ki, az lesz az aktív.



Most pedig alakítsuk ki mi látszódjon az oldalon, amikor az egyes menüpontokra kattintunk. A main script előtti div-et cseréljük le erre a kódra:

     <div class="container-fluid" ng-show="isActive('home')">
        Főoldal
    </div>
    <div class="container-fluid" ng-show="isActive('works')">
        Munkáim
    </div>
    <div class="container-fluid" ng-show="isActive('about')">
        Rólam
    </div>
    <div class="container-fluid" ng-show="isActive('tutorials')">
        <p>Szeretsz már webfejleszteni?</p>
        <img src="200.gif">
    </div>

Mint látod, itt is az isActive függvényt használjuk azzal a különbséggel, hogy az ng-show  direktívát használjuk. Ez csak akkor mutatja az adott szakaszt, ha a kifejezés értéke igaz, azaz ha az aktuális oldal aktív. Hogy érdekesebb legyen a helyzet, adjunk hozzá egy képfájlt a public mappa alá, és hivatkozzuk be a fenti módon, az img után. 

A végső kód innen letölthető



Tippek, trükkök

  • Az ng-show párja az ng-hide, ami akkor rejti el az elemet, ha a mögötte levő kifejezés értéke igaz
  • Javascriptben a ' is megengedett a string-ek jelzésére, tehát 'teszt' vagy "teszt". Ez különösen akkor hasznos, ha a fent látható módon meg kell adnod egy függvényt egy direktíva kezelőjeként
  • További linkek angularJS-hez és bootstrap-hez
  • Ha tetszik a blog, iratkozz fel itt vagy az oldal tetején jobb oldalt.



Ha bármi kérdésed van nyugodtan jelezz vissza ezen az anonym visszajelző formon





Nincsenek megjegyzések:

Megjegyzés küldése