Struttura di una applicazione UI5
Prosegue da: Creazione di una webapp in OpenUI5
Come visto nel precedente post, la struttura base di una applicazione UI5 è abbastanza contorta. Proverò a fare un pò di chiarezza spiegandone a grandi linee le componenti principali, almeno per quello che sono riuscito a capire nei quindici giorni in cui ci ho giocato. Tutto il contenuto dell'applicazione è, per convenzione, nella cartella "webapp".
I file principali nella root dell'app sono:
- manifest.json: contiene le configurazioni del progetto. In particolar modo qui vengono descritte le caratteristiche principali del progetto stesso (titolo, tipo, descrizione, dipendenze ecc..); i datasource, ovvero le sorgenti esterne di dati (servizi rest, file JSON, ecc..) e i modelli costruiti sopra di essi; la configurazione del sistema di routing, il meccanismo di navigazione interno all'app.
- Component.js: il controller di base dell'applicazione. E' usato per ospitare funzioni comuni a tutta l'applicazione, oltre che per svolgere operazioni di inizializzazione.
Sono poi state create queste directory:
- i18n: stringhe localizzate usate nell'UI.
- model: contiene file Javascript per operare sui dati (ad esempio funzioni di formattazione, o di recupero dati per le modalità non gestite nativamente da UI5).
- resources: risorse statiche (immagini eccetera).
- css: autoesplicativo.
- view: file XML che rappresentano elementi grafici (schermate o parti di esse). Tutti i files hanno estensione .view.xml.
- controller: file Javascript che contengono le funzionalità usate dagli elementi grafici. Tipicamente c'è un controller per ciascuna view. Tutti i files hanno estensione .controller.js.
Le cartelle più interessanti per un primo approccio sono le ultime due elencate sopra: la struttura degli elementi grafici (di primo acchito le pagine) e le relative funzionalità implementate in Javascript. L'applicazione che abbiamo inizializzato nel precedente post ha un'unica pagina (per giunta spoglia). La vista è realizzata così:
<mvc:View controllerName="it.tutorial.provaUI5.controller.MainView"
displayBlock="true"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<App id="idAppControl" >
<pages>
<Page title="{i18n>title}">
<content></content>
</Page>
</pages>
</App>
</mvc:View>
Il blocco view contiene il riferimento al nome del controller e i namespace (le "librerie" di componenti XML utilizzabili in questo contesto). Il resto dell'applicazione è un oggetto di tipo app, che a sua volta contiene un blocco pages, che a sua volta contiene una Page con una proprietà (title), che a sua volta contiene un content (per ora vuoto).
Si noti come il titolo della pagina è rappresentato con questa dicitura:
{i18n>title}
Le parentesi graffe indicano il fatto che il contenuto sarà interpretato da UI5. La rappresentazione indica che la stringa da usare è la variabile title all'interno del modello dati i18n, che è collegato di default ai file di localizzazione citati prima.
La pagina è collegata a un controller, fatto così:
sap.ui.define([
"it/tutorial/provaUI5/controller/BaseController"
], function(Controller) {
"use strict";
return Controller.extend("it.tutorial.provaUI5.controller.MainView", {
// Qui possiamo mettere ne nostre funzioni custom
});
});
Questa struttura indica ad UI5 di caricare le dipendenze esterne indicate nell'elenco (nel nostro caso it/tutorial/provaUI5/controller/BaseController), e una volta caricate costruire una estensione dell'oggetto BaseController e restituirla. Tutte le funzioni che vogliamo rendere disponibili alla view collegata a questo controller devono essere scritte dove indicato.
Tra parentesi, il BaseController non è un oggetto standard di libreria, bensì un modulo custom creato dal template e che a sua volta estende il vero oggetto base Controller. Nel BaseController sono messe le funzioni di utilità che vogliamo rendere disponibili a tutti i controller.
Proviamo a fare un piccolo esperimento: voglio mostrare del testo nella nostra pagina iniziale, e voglio fare in modo che questo testo sia letto da un modello dati custom inizializzato (in maniera banale) nel controller della pagina stessa.
A livello di controller, devo definire la funzione onInit() (funzione standard del ciclo di vita del controller, che viene chiamata all'inizializzazione) e dentro questa creare un JSONModel con dei dati statici. Il modello lo chiameremo myModel, e la stringa del titolo dara myTitle. Il file del controller sarà così (riferimenti API):
sap.ui.define([
"it/tutorial/provaUI5/controller/BaseController",
"sap/ui/model/json/JSONModel"
], function(Controller, JSONModel) {
"use strict";
return Controller.extend("it.tutorial.provaUI5.controller.MainView", {
onInit: function(){
let myModel = new JSONModel({
myTitle: "Il mio fantastico titolo!"
});
this.getView().setModel(myModel, "myModel");
}
});
});
Come si vede abbiamo aggiunto alle dipendenze JSONModel e poi abbiamo popolato la funzione onInit con la creazione del modello dati e l'associazione dello stesso alla vista.
La vista è modificata come segue:
<mvc:View controllerName="it.tutorial.provaUI5.controller.MainView"
displayBlock="true"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<App id="idAppControl" >
<pages>
<Page title="{i18n>title}">
<content>
<Text text="{myModel>/myTitle}"/>
</content>
</Page>
</pages>
</App>
</mvc:View>
Abbiamo semplicemente aggiunto un oggetto di testo, e come testo gli abbiamo passato {myModel>/myTitle}.
Avviamo il server locale:
npm start
E, alla pagina localhost:8080, dovremmo avere qualcosa del genere:
Voilà!