Oltre agli elementi visuali per la costruzione delle pagine, il framework IonicUI mette a disposizione un componente fondamentale per creare applicazioni omnichannel di successo: il page controller.
Lo scopo di questo componente è quello di organizzare la navigazione tra le varie pagine dell’applicazione in maniera coerente con il tipo di dispositivo utilizzato. A differenza degli elementi visuali, il cui codice sorgente è puro JavaScript, il page controller è nella videata MainPage, creata con Instant Developer Cloud e contenuta nella libreria personalizzata Ionic che viene importata con il package IonicUI.
Per utilizzare il page controller nella propria applicazione è sufficiente creare una videata, ad esempio di nome Pages, e cambiare l’estensione da Application.View ad Ionic.MainPage. Subito dopo aver compiuto questa operazione, all’interno della videata che prima era vuota appariranno le strutture personalizzabili del page controller, come mostrato nell’immagine seguente.
Il page controller è quindi costituito da una sezione visuale in cui inserire il menu dell’applicazione, da una seconda sezione visuale utilizzata per contenere le pagine che man mano appariranno, ed infine da una serie di metodi ereditati dalla classe base MainPage.
In questo paragrafo verranno illustrati i metodi principali; se si desiderano maggiori informazioni sul funzionamento interno del page controller è possibile leggere il codice sorgente contenuto nella videata MainPage della libreria Ionic.
Definizione e controllo del menu principale #
La definizione del menu principale avviene direttamente nella videata Pages della propria applicazione. L’intestazione del menu può essere gestita tramite gli elementi menubar e menutitle, mentre gli item del menu andranno inseriti all’interno di menucontent.
Per creare gli elementi visuali delle righe di menu si consiglia di creare una lista tramite IonList, IonItem e IonLabel. L’immagine seguente mostra il menu del progetto di esempio Mobile Design Patterns che può essere utilizzato come referenza.
Se il menu viene definito dinamicamente invece che a design time, sarà possibile inserire una datamap, eventualmente con raggruppamento, per generare la lista degli item.
Per ogni riga del menu dovrà essere gestito l’evento onClick, in modo da aprire la videata corrispondente. Continuando l’analisi dell’esempio precedente vediamo il seguente codice:
$first.onClick = function (event)
{
view.push(App.FirstPage, {root : true, remove : true});
view.hilightMenu(this);
view.hideMenu();
};
La prima riga chiama il metodo push del page controller per aprire la videata corrispondente alla voce di menu, chiudendo tutte quelle precedentemente aperte. Il metodo push sarà analizzato in seguito.
La seconda riga chiama il metodo hilightMenu del page controller che aggiunge la classe CSS menu-hilight alla voce di menu. Se questa classe viene definita nel foglio CSS dell’applicazione, sarà possibile evidenziare la voce di menu attiva con un colore di sfondo. Un esempio di definizione della classe può essere la seguente:
.menu-hilight {
background-color : #0fb340;
color : white;
border-radius: 0;
}
.menu-hilight ion-icon {
color: white;
}
Infine l’ultima riga chiama il metodo hideMenu del page controller che nasconde il menu se il device è uno smartphone o un tablet verticale.
La gestione del menu richiede inoltre che, in ogni videata che può essere aperta tramite menu, la proprietà menuButton della navbar abbia valore true e che venga implementato l’evento onMenuButton della navbar con il seguente codice:
$navbar.onMenuButton = function (event)
{
App.Pages.showMenu(app);
};
In questo modo, se il device è di tipo smartphone o tablet verticale, apparirà un pulsante in alto a sinistra per aprire il menu e, quando l’utente lo cliccherà, verrà chiamato il metodo showMenu che mostra il menu con un’animazione. In caso di tablet orizzontale o desktop il framework fa in modo che il menu sia sempre visibile e che i pulsanti di apertura del menu nelle navbar non appaiano. È possibile modificare il comportamento standard tramite la proprietà exposed dell’elemento IonSplitPane contenuto nella propria videata Pages.
L’ultimo metodo del page controller da utilizzare per il controllo del menu è enableMenu. Esso deve essere chiamato quando la sessione di lavoro entra in uno stato in cui il menu non può essere usato, come ad esempio durante la fase di login.
In questi casi è necessario chiamare il metodo enableMenu del page controller passando il parametro false per impedire l’uso del menu dell’applicazione. Questa chiamata può essere effettuata, ad esempio, nell’evento onLoad della videata di login, come mostrato di seguito.
App.Login.prototype.onLoad = function (options)
{
App.Pages.enableMenu(app, false);
...
};
Se il login ha successo, è necessario attivare nuovamente il menu chiamando enableMenu,questa volta passando true come parametro.
Aprire una videata #
L’apertura di una videata avviene tramite il metodo push del page controller, solitamente chiamato in modo statico tramite l’istanza di default: App.Pages.push(app, App.Login).
Il metodo push ammette due parametri. Il primo è la classe che rappresenta la videata da aprire, il secondo è un oggetto che rappresenta le opzioni di apertura che verranno passate all’evento onLoad della videata.
L’apertura potrà avvenire in diversi modi in funzione delle opzioni passate come parametro. In particolare il page controller gestisce le seguenti:
- root:true – La videata rappresenta un nuovo percorso di navigazione; si consiglia di utilizzare questa opzione quando si apre una videata tramite il menu dell’applicazione e, in questi casi, di applicare sempre anche l’opzione remove:true. Specificando questa opzione non viene usata l’animazione di apertura, ma la videata appare immediatamente.
- remove:true – Dopo aver aperto la nuova videata, tutte le videate precedenti vengono chiuse.
- remove:<n> – Dopo aver aperto la nuova videata, le n videate precedenti vengono chiuse. n deve essere un numero intero maggiore di zero.
- animate:false – Disabilita l’operazione di apertura.
- popup:true – Apre la videata come popup. In questo caso è possibile utilizzare anche le altre opzioni ammesse dal metodo show di una videata come, ad esempio, modal:true per ottenere un popup modale.
- autoclose:false – In caso di popup impedisce di chiudere la videata cliccando all’esterno di essa.
- wait:false – La videata appare prima possibile. Se non specificato, il page controller aspetta 100 ms prima di effettuare l’animazione di apertura per dare tempo alla videata di preparare il proprio aspetto visuale.
Si ricorda che nelle opzioni di apertura si potranno specificare le opzioni personalizzate che devono essere passate all’istanza di videata che viene aperta. Ad esempio questa riga di codice passa il documento da una lista ad una videata di dettaglio.
$item.onClick = function (event)
{
App.Pages.push(app, App.DettaglioProdotto, {doc : this.row.document});
};
Chiudere una videata #
La chiusura di una videata avviene tramite il metodo pop del page controller. Tale metodo ammette due parametri. Il primo rappresenta il numero di videate da chiudere (per default una), il secondo è un oggetto che rappresenta le informazioni che verranno passate alla videata che diventa attiva.
L’operazione di chiusura avviene come segue:
- viene notificato l’evento onBack sulla videata che diventa attiva, passando le eventuali informazioni inserite come secondo parametro.
- viene eseguita l’animazione di “ritorno indietro” dipendente dal dispositivo utilizzato.
- Quando l’animazione è terminata ed è diventata già attiva una nuova videata, vengono chiuse le videate indicate. A tali videate viene notificato l’evento onClose.
Come si può notare, il metodo pop non è interrompibile, cioè le videate vengono rimosse comunque dal video. Per tale ragione si consiglia di non restituire mai il valore false nell’evento onClose perché in tal caso la videata sparisce dal video, ma la memoria allocata non viene liberata.
Di solito il metodo pop viene chiamato dal codice applicativo quando si verificano le condizioni per tornare alla videata precedente, come vediamo nell’esempio seguente:
// Chiude la videata attuale e ritorna alla precedente
App.Pages.pop(app);
Esiste un caso particolare in cui la chiamata al metodo pop viene generata dal framework. Questo avviene quando l’utente preme il pulsante back della navbar di una videata o esegue il gesto di edge swipe dal lato sinistro dello schermo. In questo caso, se per la videata non viene implementato l’evento onBackButton della navbar, il framework esegue automaticamente il metodo pop chiudendo la videata attuale.
Se si desidera impedire la chiusura della videata o comunque controllare il processo di chiusura, è necessario implementare l’evento onBackButton della navbar e nel codice che gestisce l’evento scegliere se chiamare o meno il metodo pop. Se l’evento onBackButton viene implementato, il framework non genera la chiamata automatica a pop.
Inviare messaggi alle videate #
Il framework di Instant Developer Cloud comprende alcuni sottosistemi che sono in grado di generare eventi in maniera indipendente dall’interfaccia utente.
Ad esempio, se un utente effettua l’upload di una fotografia catturata con l’applicazione, al termine del caricamento viene notificato alla sessione l’evento onTransfer da parte del plugin fotocamera. Un altro caso riguarda il sottosistema di sincronizzazione, che notifica eventi relativi ad aggiornamenti dei documenti o al processo di sincronizzazione stesso.
In questi casi è utile informare le videate aperte delle novità avvenute. A tal fine il page controller contiene il metodo postMessage con cui è possibile avvisare dell’accaduto la videata attiva o tutte le videate aperte. postMessage ammette un solo parametro di tipo oggetto che contiene tutte le informazioni da notificare. Se la proprietà bc di questo oggetto è true, allora il messaggio verrà notificato a tutte le videate aperte, altrimenti solo a quella attiva.
Le videate ricevono le informazioni implementando l’evento onMessage. Vediamo un esempio di codice relativo all’upload di foto tramite fotocamera.
Nel plugin camera contenuto nell’oggetto device definito a livello di applicazione possiamo implementare l’evento onTransfer scrivendo il seguente codice:
app.device.camera.onTransfer = function (event)
{
// Post the photo to the current view (edit item page)
App.Pages.postMessage(app, {type : "camera-transfer", event : event});
};
A questo punto nella videata che deve visualizzare la foto, potremo utilizzare le informazioni arrivate dal plugin camera:
App.EditItem.prototype.onMessage = function (message)
{
if (message.type === "camera-transfer") {
view.itemToEdit.Photo = app.sync.serverUrl + "/" + app.sync.appName +
"/files/uploaded/" + view.fileName;
view.itemToEdit.FileName = view.fileName;
}
};
È possibile visualizzare il codice completo nel progetto di esempio ToBuy.
Personalizzare il funzionamento del page controller #
Come abbiamo visto nei paragrafi precedenti, il page controller è implementato tramite codice Instant Developer Cloud. È quindi possibile leggere il codice completo del componente aprendo la libreria importata Ionic e sfogliando i metodi della videata MainPage.
Siccome il metodo predefinito per implementare un page controller è quello di creare nella propria applicazione una videata che estende Ionic.MainPage, sarà possibile personalizzare il funzionamento del page controller sovrascrivendo i metodi base.
Se, ad esempio, si sovrascrive il metodo canClose di MainPage inserendo un metodo sovrapposto nella propria videata Pages, si potrà definire se l’applicazione si deve chiudere al momento in cui l’utente clicca ancora il pulsante back e non ci sono videate aperte nel page controller.
Se, ad esempio, si vuole chiedere all’utente cosa preferisce fare, si potrebbe utilizzare il seguente codice:
App.Pages.prototype.canClose = function ()
{
return yield app.confirm(“Vuoi chiudere l’applicazione?”);
};