Angular-frameworkia käytetään portleteissa neljässä yhteydessä:
(1) JSP-tiedostoissa (tiedosto vastaa yhtä websivua), jossa se määrittelee Angularin MVC-mallin sidonnan HTML-elementteihin.
(2) Javascript-tiedostoissa, joissa Angularin moduleiden ja kontrollereiden määritys on.
(3) Bootstrap-toiminto, joka on viimeiseksi ladattavassa Javascript-tiedostossa.
(4) Javascript-tiedosto, jossa on toteutettu sivunvaihdot (router).
(1) JSP-sivu ja Angular:
JSP-sivu ei ole ongelma HTML-tagituksen ja siihen liittyvän Angularin suhteen, koska HTML- ja Javascript-osuuksia ei JSP-sivua ladattaessa prosessoida. Avaavalla JSP-sivulla merkitään ainoastaan mihin kohtaan uusi sivu aina vaihdetaan, mikä on siten SPA-portletin pääkehys. Tämä on ainut avaavan JSP-sivun HTML-tagitus tässä seppien esimerkissä. Toki voi avaavalle sivulle muutakin kiinteää HTML-sisältöä lisätä. Nämä lisäykset luonnollisesti näkyvät kaikkien avattavien sivujen ympärillä, koska avattava uusi sivu on vain div-elementin uusi sisältö. Kehys merkitään esimerkiksi näin, eli se sisältää ng-controller direktiivissa Angularin kontrollerin määrityksen sekä sivunvaihdon mahdollistavan ng-view direktiivin:
Div-elementin attribuutit: id=”div0″ ng-controller=”dataGridCon” ng-view
Muut JSP-sivut taas muodostavat SPA-portletin varsinaisen sisällön, ja ne avataan edellä määriteltyyn div-elementtiin. Niiden alkuun tarvitaan apua JSP-tagitukselta (ajetaan serverin puolella) portletin namespacen hakemiseen JSP-sivua ladataessa (ks. aikaisemmat blogit, mihin se kirjoitetaan talteen). JSP-sivun alkuun siis tarvitaan merkinnät (POUtil on yksinkertainen Java-luokka lukemiseen):
<%@ page import=”fi.fabercon.portlet.util.PoUtil” %>
<% String ns = PoUtil.getNamespace(); %>
Tämä namespace tieto Javassa (ns) on sama, kuin mikä luetaan avaavassa JSP-sivussa selaimessa Javascriptin globaaliin muuttujaan (ns.namespace). Tämän jälkeen Angularin lisääminen JSP-sivulla on yksinkertaista, käytät vain edellä haettua ns-muuttujaa identifioimaan elementteja. Muuten merkinnät ovat täysin Angularin yleisten esimerkkien mukaisia. Mitään Angularin ng-controller määritystä ei muille kuin avaavalle JSP-sivulle siis tule. Nämä määritykset hoidetaan Angularin $route-servicen määrityksessä. Esimerkiksi button-input-elementin sidonnasta Angulariin (ng-click on Angular-direktiivi):
<input type=”button” id=”<%=ns%>btnSelect” value=”Select by Id” ng-click=”btnSelectItem_click();” />
Tai text-input-elementin kaksisuuntainen sidonta Angularin Modelilta tuomaan dataan:
<input type=”text” id=”<%=ns%>txtName” ng-model=”company.name” value=”{{company.name}}” />
Alisivuilla ei tarvita mitään muuta. Angular-controllerin määritykset ovat SPA-portletissa avaavalla JSP-sivulla.
(2) Javascriptiin sijoitettu Angular-koodi:
AngularJS-koodi sijoitetaan Angular-kontrollereihin. Selkeänä perustana kannattaa pitää yksi moduli ja sen ainut kontrolleri per tiedosto. Yksi Angular-javascript-tiedosto kapseloi siis yhden kontrollerin, eli yhden JSP-sivun Javascript-koodin. Angular-modulit määritettiin avaavalla JSP-sivuilla ja globaalit muuttujat kapseloitiin getNamespace-metodissa.
Angular-modulin ja -controllerin määritys ei poikkea tavanomaisesta Angularin käytöstä web-sivuilla. Tiedoston perusrakenteesta esimerkki:
var ns = gsPortletinNimiNS; // siirto helppoon lokaaliin muuttujanimeen
console.log(”javascript-tiedoston-nimi: ” + ns);
ns.controlMod.controller(ns.namespace + ”dataItemCon”, [ ”$scope”, ”$routeParams”, ”angService”,
function($scope, $routeParams, angService)
{
// modulin toteutus: muuttujat, funktiot, $scope-muuttujat, @scope-funktiot ym.
}
Angularin modulin määritys löytyy Angularin massiivisesta dokumentaatiosta. Kontrollerin sisältö on tavanomainen (ikäänkuin Javan luokkamääritys), siellä voidaan määritellä:
– normaaleja Javascript-funktioita
– $scope-funktioita (esim. $scope.btnSelectItem_click = function (…) {….} ) ovat funktioita, joita käytetään Angular-modulin rajaamalta alueelta, esimerkiksi HTML-elementtien tapahtumankäsittelyfunktioina.
– normaaleja Javascript-muuttujia, joissa voidaan tallettaa tietoja (ts. sovelluksen tilaa)
– $scope-muuttujat (esim. $scope.company) ovat lisäksi tarkoitettuja sitomaan data HTML-elementteihin
– $scope-muuttujat ja -funktiot muodostavat modulin julkisen rajapinnan, muu ei näy modulin ulkopuolelle
(3) Bootstrap-toiminto:
AngularJS lataa (sisäinen bootstrap) modulit ja servicet automaattisesti, jos niiden latausta ei määritellä. On hyvin todennäköistä, että SPA-toiminto ei vaadi erillistä latausta, mutta monimutkaisissa tilanteissa ei ole varmuutta miten automaattinen lataus toimii. Tämän takia on varmempaa määritellä lataus ei bootstrappaus itse viimeiseen ladattavaan Javascript-tiedostoon, kun kaikki määrittelyt ovat valmiina.
Portleteissa Eclipse IDEn wizard laatii aina mukaan main.js-tiedoston. Tämä sopii bootstrapin paikaksi. Liferay-portlet.xml -tiedostossa kyseisen tiedoston lataus pitää olla viimeisenä. Esimerkki main.js:n sisällöstä:
var ns = gsPortletinNimiNS;
var divElem = document.(ns.namespace + ”div0”);
angular.bootstrap(divElem, [ ns.namespace + ”appMod” ]);
DivElem-muuttuja viittaa avaavan JSP-sivun SPA-kehyksen div-elementtiin.
(4) Angularin route-toiminto:
Seuraavassa blogissa käsitellään Angularin $route-toimintoa SPA-portletissa.