11. gyakorlat¶
Saját tagek (Custom tags)¶
A felhasználó saját maga hozhat létre új tagaket. Ezáltal segít abban, hogy ne kelljen scriptleteket használni, illetve segít szeparálni az üzleti logikát a megjelenítéstől. Ezek mellett talán a legnagyobb előnye, hogy ezeket a tageket újra fel tudjuk használni több helyen is. Kétféleképpen használhatjuk a saját tagjeinket:
1 2 3 4 5 6 7 | |
A saját tagek definíciójához nagyobb szabadságot ad, ha TLD-ket (Tag Library Descriptor-okat) adunk meg, de ez túlmutat a céljainkon, mivel kicsit nehézkes és több helyen kell ezeket megadni.
Egy másik, egyszerűbb módja, hogy a tag definíciókat a WEB-INF/tags mappában helyezzük el. Készítsük el a current-datetime taget!
WEB-INF/tags/current-datetime.tag
1 2 3 4 5 6 | |
Figyeljük meg, hogy a page direktíva helyett azt írtjuk, hogy tag, ezzel is jelezvén, hogy egy saját tag-et definiálunk.
A tag egyszerűen kiírja az aktuális dátumot és időt.
Használata, index.jsp
1 2 3 4 | |
A taglib direktívában nem az uri-t kell megadnunk, hanem a tagdir attribútumban a saját tagjeink könyvtárát. Innentől már használhatjuk a tags könyvtárban lévő tageket mint például a current-datetime-ot.
Custom tagek attribútumai¶
Az előző példában csak egy tag-et csináltunk, de annak nem voltak attribútumai, ami viszont egy elég általános elvárás egy saját tag-től.
Készítsük el azt a saját tag-et amelyet a következőképpen tudunk használni:
1 | |
Ehhez készítünk egy cube.tag állományt a WEB-INF/tags mappába, melynek tartalma:
1 2 3 4 5 6 7 | |
<%@ attribute %> direktívával adhatunk meg.
Ez a direktíva csak tag definícióknál használható, jsp oldalaknál nem.
Az attribútumnak meg lehet adni a nevét, hogy kötelező-e, mint azt a fenti példában is láthatjuk.
Nagyon fontos a type attribútum.
A példában a 3. hatványra emelő tagünknek egy számot kell várnia, azonban az attribútumok alaptípusa java.util.String.
A mi esetünkben ez egy nagy exception-t eredményezne, mivel arra nem tudja értelmezni a value * value kifejezést, így a type-ot megadtuk, hogy Double-t várjon és így működik is a tag.
Ezen felül az attribútumnak adhatunk leírást is a description megadásával.
Amennyiben nem attribútumban, hanem a tagek között akarjuk megadni az értéket a cube-nak, akkor a következőt kell tennünk:
1 2 3 4 5 6 7 8 | |
A jsp:doBody segítségével a custom tagünk közötti body részt értékelhetjük ki. A kiértékelés eredményét egyből nyomhatjuk az outba, ekkor nem kell sem a scope sem a var attribútumot használnunk. Ha viszont szeretnénk felhasználni az értékét később, akkor érdemes lehet eltárolni, mint ahogyan most is ki akarjuk számolni a köbét. Ehhez kiolvassuk a tartalmat, majd string-é alakítjuk és trimmeljük, hogy tudjunk parsolni olyat is ha különböző sorban van a nyitó és záró tag, illetve közte az adat. Használni egyszerűen a következőképpen lehet:
1 | |
Az attribute direktívának van egy további paramétere, mégpedig, hogy az attribútum az fragment-e. Ez azt jelenti, hogy a tag paraméterül jsp kódrészletet kap. Ezek nagyon jól használhatóak, ha például template-et kell készítenünk az oldalainkhoz.
A cube tag-et bővítsük, hogy benne még további jsp-t adhassunk meg! A tag definícióban az alábbiakat kell írnunk:
1 2 3 4 5 6 7 8 9 10 | |
<jsp:invoke> használatával illeszthetjük be.
Ezt akár több ponton is megtehetjük.
Ezután a használatát tekintve a következőket kell tennünk:
1 2 3 4 5 | |
Most, hogy az alapokat megnéztük ideje, hogy átalakítsuk az alkalmazásunkat úgy, hogy az page template-eket használjon. Az esetleges újdonságokat menet közben még tisztázzuk.
Feladat
Alakítsuk át úgy a contacts alkalmazásunkat, hogy page template-eket használjon!
Először is különböztessük meg azt a különböző eseteket, amikre szükségünk lehet:
- Common header szükséges az oldalhoz
- Common header és menü is szükséges az oldalon
Ez alapján kétféle page template-et fogunk elkészíteni.
Vegyük az elsőt, melyben csak a common header lesz benne.
Ehhez a WEB-INF alatt hozzuk létre a tags könyvtárat, ahol létrehozzuk a basic-layout.tag állományt, melynek a következő tartalma lesz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
A fájl elején megadjuk, hogy egy custom tag-ről van szó (aminek neve megegyezik a fájl nevével: basic-layout), majd megadjuk, hogy milyen attribútumokat fogunk használni ebben a tag-ben.
Az első attribútum a title, mely az oldal címét adja meg és annak típusú String.
Ha megnézzük, hogy hol használjuk fel a title attribútumot, akkor láthatjuk, hogy a <title>${title}</title> megadásban szerepel, ami az oldal címét adja meg.
Ilyenkor a tag-et a következőképpen fogjuk használni: <basic-layout title="Login">...</basic-layout>, melynek eredményeképpen a megadott oldal címe Login lesz.
A <head> részben a korábban common-header.jsp oldalon megadott elemeket helyezzük el.
Ugyanakkor itt van még egy fontos pont, amikor meghívjuk a header attribútumot, amely viszont már egy fragment a title-el ellentétben, így az tartalmazhat HTML részfát is akár.
Erre azért van szükség, mert az egyes oldalak esetleg tovább szeretnék bővíteni a <head>-ben megadott elemeket, mint például az add-contact.jsp-ben szeretnénk használni az add-contact.js állományt (máshol viszont nem).
Ugyanezt végezzük el a footer-re, melyet jelenleg ugyan nem használunk, de később jól jöhet.
A használat helyén a <basic-layout title="xxx">...</basic-layout> között megadott tartalmat a <jsp:doBody/> hívással írhatjuk ki a template-ben.
Ezt a tartalmat egy div-ben helyezzük el <div id="body" class="container">.
Miután megvan a template, nézzük, hogy hogyan használhatjuk fel azt például a login.jsp oldalon:
1 2 3 4 5 6 7 8 | |
A fenti példában a behúzzuk a használni kívánt tagek mappáját: tagdir és adunk neki egy prefixet, mely most a t.
Ezután egyszerűen használjuk a saját basic-layout tag-ünket, ahol megadjuk a title attribútumot.
Most a megadott <form> elem kerül a template-ben megadott <jsp:doBody/> helyre.
A teljesség kedvéért alul látható a böngészőben elérhető HTML, ahol már a saját tag- feloldását láthatjuk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
Ezt az alap template-et a login mellett a register.jsp is használja, mely nagyon hasonló lesz a login-hoz:
1 2 3 4 5 6 7 8 | |
Az eddigi form-ot átmozgattuk a basic-layout tag body részébe, illetve más title-t adtunk meg, de más különbség nincs.
Ezután nézzük meg azt, hogy hogyan használhatjuk fel a basic-layout tag-et egy másik tag definíciójában, azaz hogyan bővíthetjük ezt a tag-et (a menüvel).
Nyilvánvalóan a basic-layout-ban szereplő elemeket szeretnénk a basic-layout-menu tag-ben is alkalmazni, viszont kódot nem szeretnénk duplikálni.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
Mivel hasonlóan meg szeretnénk adni egy basic-layout-menu tag-nek is a title-t, az esetleges header-t és footer-t, így ezeket az attribútumokat itt is "kivezetjük", melyeket majd továbbadjuk a basic-layout-nak.
Ez látszódik például a <t:basic-layout title="${title}"> sorban is.
A header és a footer megadása kicsit másképpen működik.
A header beillesztéséhez a <jsp:invoke fragment="header" />-ot kell meghívnunk, melyet "kívülről" kapunk.
Mivel ezt a <t:basic-layout>-nak szeretnénk továbbadni, így itt meg kell adni, hogy a basic-layout header attribútumát szeretnénk beállítani, ezért kell a <jsp:attribute name="header"> megadás.
Hasonlóképpen a kívülről kapott basic-layout-menu tartalmát tovább szeretnénk adni a basic-layout body-jaként, így ezt <jsp:body> tag-ek között kell megadnunk.
Annyi a különbség, hogy a kívülről kapott body HTML tartalom elé berakjuk a nav-ot, azaz a menüt.
Nézzük, hogy hogyan használja fel a list-contact.jsp oldal a template-et:
1 2 3 4 5 6 7 8 9 10 11 | |
A tag felhasználása a megszokott módon történik, nincs semmi mágia.
A különbség annyi, hogy most már a <basic-layout-menu> tag-et használjuk.
Viszont van egy fontos különbség, akkor amikor a header-be vagy a footer-be is bele szeretnénk valamit rakni.
Ez igazából hasonlóan megy, mint a basic-layout-menu-nél.
Lássuk az add-contact.jsp oldalt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Szokásos módon behúzzuk a használni kívánt tag-ek könyvtárát: <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>.
Ezután a <basic-layout-menu>-on belül a header-t szeretnénk megadni, ahol a <script src="${pageContext.request.contextPath}/js/add-contact.js"></script> bővítést szeretnénk eszközölni.
Ezután pedig a body-ban megadni a useBean-nel a megfelelő Contact objektumot és a form-ot.
Amennyiben nem jeleznénk, hogy mi a header attribútum és mi a basic-layout-menu body-ja, akkor a rendszer mindent body-nak venne, így megadjuk a header attribútum értékét a <jsp:attribute name="header"> tag használatával, illetve a <jsp:body>-val magát basic-layout-menu body-ját.
A profile.jsp oldalon hasonló módosításokat kell tennünk, mint az add-contact.jsp-n, így azt itt már nem mutatjuk be.
Ezzel elkészítettük a kontakt alkalmazásunk webes változatát is. A teljes projektet lásd a pub-on!