UI5: navigazione tra pagine

Continua da qui: Struttura di una applicazione UI5

Le applicazioni UI5 sono tipicamente SPA (single page application); questo significa che, dal punto di vista del browser, sono viste come un'unica pagina HTML. Naturalmente, è difficile realizzare una applicazione completa con una singola schermata. Per ovviare a questo problema, il framework ci mette a disposizione un router, ovverossia un componente interno che consente di "navigare" tra diverse schermate dell'applicazione senza spostarci fisicamente verso un altro file HTML.

Il componente router è dichiarato nel manifest.json, e qui andremo a configurarlo. Per cominciare andiamo a vedere la sezione sap.ui5 del nostro manifest:

  ...
  "sap.ui5": {
    "rootView": {
      "viewName": "it.tutorial.provaUI5.view.MainView",
      ...

In questa sezione è definita la schermata principale della nostra applicazione, che abbiamo chiamato MainView.

Spostiamoci poi sotto, nella sezione routing. In questa sezione sono presenti tre parti: config, routes e targets.

La parte di config contiene i parametri generali di configurazione del sistema di routing.

      "config": {
        "routerClass": "sap.m.routing.Router",
        "viewType": "XML",
        "viewPath": "it.tutorial.provaUI5.view",
        "controlId": "idAppControl",
        "controlAggregation": "pages",
        "async": true
      },

Le chiavi più interessanti sono "viewPath", che contiene il namespace di base da cui andare a leggere le view; il "controlId", che contiene l'id del componente nella view principale in cui andare a iniettare le pagine aperte dal router; il "controlAggregation", che contiene il nome del componente XML da inserire all'interno del componente con id controlId, per potervi iniettare le pagine (torneremo su questi concetti più avanti con un esempio).

La parte routes contiene i pattern per riconoscere le route. Ogni visualizzazione all'interno dell'applicazione è raggiungibile aggiungendo all'URL della (unica) pagina HTML un parametro, che verrà confrontato con i pattern elencati in questa sezione e causerà l'apertura della schermata corrispondente (anche qui sarà più chiaro dopo un esempio).

La parte targets, infine, descrive la lista delle schermate a cui puntano le routes viste sopra.

Proviamo a implementare un semplice routing nella nostra applicazione di prova. La parte di config la lasciamo così com'è, poichè ci va bene usare la MainView come vista principale. Dobbiamo solo modificare la MainView.view.xml per togliere tutto; la MainView diventerà infatti un semplice contenitore vuoto in cui caricare altre schermate. Una cosa del genere:

 <mvc:View controllerName="it.tutorial.provaUI5.controller.MainView"
  displayBlock="true"
  xmlns="sap.m"
  xmlns:mvc="sap.ui.core.mvc">

  <App id="idAppControl" />
  
</mvc:View>

Come si vede, abbiamo tolto tutto il contenuto della sezione "App" e abbiamo verificato che il suo id sia "idAppControl", come definito nella parte config del manifest.

A questo punto possiamo creare una nuova vista da caricare qui dentro. Creiamo un file "FirstView.view.xml" nella cartella "view":

 <mvc:View controllerName="it.tutorial.provaUI5.controller.FirstView"
  displayBlock="true"
  xmlns="sap.m"
  xmlns:mvc="sap.ui.core.mvc">

  <Page title="Prima vista">
    <Button text="Fai qualcosa" press="onPress" />
  </Page>
  
</mvc:View>

Creiamo anche il suo controller FirstView.controller.js (per ora vuoto):

sap.ui.define([
  "it/tutorial/provaUI5/controller/BaseController"
], function(Controller) {
  "use strict";

  return Controller.extend("it.tutorial.provaUI5.controller.FirstView", {

  });

});

Andiamo a modificare la parte routes del manifest. Togliamo la route predefinita e ne creiamo una con pattern vuoto (quella di default).

      "routes": [
        {
          "name": "FirstRoute",
          "pattern": "",
          "target": [
            "FirstView"
          ]
        }
      ],

La nostra route di default punta a un target "FirstView". Andiamo a creare questo target:

      "targets": {
        "FirstView": {
          "viewType": "XML",
          "viewLevel": 1,
          "viewId": "FirstView",
          "viewName": "FirstView"
        }
      }

Il "viewName" è il nome della vista che verrà iniettata, e il "viewId" è l'id che verrà assegnato a questa nuova vista (un id qualunque va bene purchè non sia duplicato su altri elementi nella pagina).

A questo punto, se abbiamo fatto le cose per bene, dovrebbe essere possibile avviare l'applicazione (npm start) e vedere nel browser la nostra prima vista:

Adesso proviamo la navigazione. Per prima cosa dobbiamo creare una seconda vista, chiamata SecondView. Creiamo view e controller:

 <mvc:View controllerName="it.tutorial.provaUI5.controller.SecondView"
  displayBlock="true"
  xmlns="sap.m"
  xmlns:mvc="sap.ui.core.mvc">

  <Page title="Seconda vista">
  </Page>
  
</mvc:View>
sap.ui.define([
  "it/tutorial/provaUI5/controller/BaseController"
], function(Controller) {
  "use strict";

  return Controller.extend("it.tutorial.provaUI5.controller.SecondView", {

  });

});

Aggiungiamo nel manifest un nuovo pattern "qualcosa" con il relativo target, che facciamo puntare alla nostra SecondView:

      "routes": [
        {
          "name": "FirstRoute",
          "pattern": "",
          "target": [
            "FirstView"
          ]
        },
        {
          "name": "SecondRoute",
          "pattern": "qualcosa",
          "target": [
            "SecondView"
          ]
        }		
      ],
      
      "targets": {
        "FirstView": {
          "viewType": "XML",
          "viewLevel": 1,
          "viewId": "FirstView",
          "viewName": "FirstView"
        },
        "SecondView": {
            "viewType": "XML",
            "viewLevel": 1,
            "viewId": "SecondView",
            "viewName": "SecondView"
        }
      }

A questo punto dobbiamo solo creare la logica per invocare la "SecondRoute". Nella view della prima vista abbiamo già creato un pulsante "fai qualcosa" che ha coma callback un metodo "onPress". Adesso andiamo a implementare il metodo stesso nel file "FirstView.controller.js":

sap.ui.define([
  "it/tutorial/provaUI5/controller/BaseController"
], function(Controller) {
  "use strict";

  return Controller.extend("it.tutorial.provaUI5.controller.FirstView", {

    onPress: function (oEvent) {
      var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
      oRouter.navTo("SecondRoute");
    }

  });

});

Se tutto va per il meglio, dopo aver ricaricato la pagina possiamo premere il pulsante "fai qualcosa" e voilà!

Da notare che quando si apre la seconda vista il pattern è visibile nell'url della pagina dopo il #:

localhost:8080/index.html#/qualcosa