Definizione di videata #
Una videata rappresenta la definizione di una classe di codice di Instant Developer Cloud utilizzata per implementare l’interfaccia utente dell’applicazione. Una classe, per essere considerata come videata, deve derivare, direttamente o indirettamente, dalla classe Application.View del framework.
Solitamente le videate vengono inserite all’interno dell’oggetto applicazione di cui fanno parte, ma è possibile definire le videate anche all’interno di librerie di tipo custom. Quest’ultima opzione è particolarmente efficace per videate generiche che possono essere utilizzate in progetti o applicazioni diversi.
All’interno di una videata è possibile inserire elementi grafici di tipo diverso. Tali elementi devono essere presenti nel progetto all’interno della sezione librerie. Il pacchetto coreLibraries, incluso in tutti i progetti, contiene la definizione degli elementi base dell’HTML. Di solito si consiglia di aggiungere al progetto il pacchetto IonicUI che contiene l’insieme degli elementi grafici del framework Ionic adatto alla creazione di applicazioni di tipo omnichannel.
La videata YourAccount e i suoi elementi visuali
Oltre agli elementi visuali, una videata, come ogni altra classe, può includere proprietà, eventi e metodi. Per gli elementi visuali possono essere definiti gli script di gestione degli eventi da essi supportati come si vede per i pulsanti (onClick) e per il campo di input (onChange).
Ciclo di vita di una videata #
Il ciclo di vita di una videata consiste di soli due stati: una videata può essere aperta oppure chiusa.
Apertura di una videata #
Per aprire una videata, occorre semplicemente chiamare il metodo base show su una istanza della stessa oppure in modo statico sulla classe. Nell’esempio precedente, per aprire la videata YourAccount, è possibile scrivere uno dei seguenti esempi di codice.
App.YourAccount.show(app, options);
Oppure:
let v = new App.YourAccount(app);
v.show(options);
I due metodi non sono equivalenti. Nel primo caso (chiamata statica), il framework crea internamente una istanza di default della videata per la sessione app passata come parametro e poi apre quella. Tutti i metodi chiamati in modo statico sulla classe diventano infatti chiamate all’istanza di default per la sessione passata.
Il secondo metodo invece crea una istanza specifica e poi la apre. In questo modo è possibile aprire più volte la stessa videata passando parametri diversi.
Il metodo show opera come segue:
- Crea le istanze degli elementi visuali all’interno dell’istanza in fase di apertura.
- Notifica l’evento onLoad alla videata, senza aspettarne la terminazione se esso è asincrono.
- Invia al browser tramite il motore di rendering i dati per mostrare effettivamente la videata a video.
Per passare parametri alla videata in fase di apertura occorre utilizzare il parametro options del metodo show, come nell’esempio seguente.
App.YourAccount.show(app, {account: myacc});
I parametri di apertura vengono passati all’evento onLoad che li può quindi tenere in considerazione per adeguare la visualizzazione ai dati richiesti. Tra le opzioni che è possibile passare a show ce ne sono alcune predefinite che permettono di gestire il modo in cui la videata deve apparire. Ad esempio, inserendo popup:true, la videata apparirà sovrapposta alle altre. Dall’IDE è possibile leggere la documentazione completa dei parametri predefiniti.
Nota importante: il pacchetto IonicUI contiene una videata speciale (MainPage) che ha lo scopo di gestire il flusso di navigazione fra videate. Usando IonicUI le videate non devono essere aperte direttamente con show; si deve invece usare il metodo push specifico di MainPage. Per maggiori informazioni è possibile leggere la documentazione relativa.
Chiusura di una videata #
La chiusura di una videata avviene chiamando il metodo close sull’istanza o in modo statico sulla classe. In tal caso verrà chiusa l’istanza di default della sessione passata.
Di solito una videata viene chiusa da uno script contenuto all’interno della medesima. In tal caso l’istanza della videata in cui lo script è in funzione è accessibile tramite la variabile view. Per chiudere la videata attuale è quindi possibile scrivere:
view.close(info);
L’operazione di chiusura avviene con i seguenti passi:
- Viene notificato l’evento onClose alla videata attuale. Se l’evento restituisce false, l’operazione di chiusura viene annullata.
- Se la videata attuale ha una videata di riferimento (owner), viene notificato l’evento onBack alla videata di riferimento passando il parametro info. La videata di riferimento è quella che tornerà attiva quando quella attuale si chiude.
- Viene inviato al motore di rendering il comando per eliminare la videata attuale dal browser dell’utente.
Nota importante: il pacchetto IonicUI contiene una videata speciale (MainPage) che ha lo scopo di gestire il flusso di navigazione fra videate. Usando IonicUI le videata non devono essere chiuse direttamente con close; ma si deve usare il metodo pop specifico di MainPage. Per maggiori informazioni è possibile leggere la documentazione relativa.
Gli elementi visuali #
Gli elementi visuali sono i blocchi costitutivi dell’interfaccia utente che una videata mostra nel browser. Essi vengono composti tramite l’IDE, che permette di definire la struttura ad albero degli stessi, come si vede nell’immagine alle pagine precedenti.
Gli elementi disponibili dipendono dalle librerie presenti nel progetto. Il pacchetto coreLibraries, incluso in ogni progetto, contiene la definizione degli elementi base dell’HTML oltre ad una serie di elementi di più alto livello come, ad esempio, le mappe, i grafici, gli slider, ecc. Il pacchetto IonicUI contiene gli elementi necessari alla creazione di un’applicazione omnichannel responsiva (web e mobile) e il suo utilizzo è altamente consigliato in ogni progetto. È anche possibile aggiungere ulteriori elementi creando un file di interfaccia e definendo una libreria. Per maggiori informazioni fare riferimento al progetto di esempio extensibility-design-pattern.
Tutti gli elementi visuali sono istanze della classe base App.RemElem del framework. Ogni istanza viene completata per rappresentare uno specifico tipo di elemento, che può avere metodi o eventi specifici. Ogni RemElem si interfaccia automaticamente con il motore di rendering per inviare al browser le modifiche visuali oppure per notificare al codice della videata gli eventi avvenuti nel browser.
Esempio di funzionamento #
Per comprendere il funzionamento degli elementi visuali e del motore di rendering, si consideri la seguente videata.
Cambiare il testo di una label al click
Quando l’applicazione è in esecuzione e l’utente clicca il pulsante, viene generato un evento onClick all’interno del browser, e la parte client del motore di rendering “riflette” tale evento all’istanza di RemElem che rappresenta il pulsante nella videata aperta nella sessione in esecuzione nel container per applicazioni web.
Quando il codice dell’evento onClick modifica una proprietà dell’elemento label, tale modifica viene comunicata al framework client che si occupa di aggiornare il browser. La raccolta delle modifiche avviene attraverso particolari oggetti chiamati Proxy in grado di “sentire” le modifiche applicate ai RemElem in modo particolarmente efficiente.
Confronto fra RemElem e DOM del browser #
Gli elementi visuali che compongono una videata sono modellati sulla struttura degli elementi DOM del browser, in particolare supportano un sottoinsieme dell’api di questi ultimi. L’interfaccia di programmazione è descritta nelle librerie di tipo Applicazione contenute nel progetto, in particolare la classe Application.Element la cui documentazione è consultabile tramite l’IDE.
Oltre alle proprietà, ai metodi ed agli eventi specifici dei vari tipi di elementi visuali, tutti i RemElem supportano le seguenti caratteristiche:
- Generazione automatica degli id. L’id di ogni elemento viene generato automaticamente e non deve essere modificato.
- Possibilità di impostare classi CSS tramite la proprietà className. Le classi CSS potranno essere manipolate tramite i metodi addClass, removeClass, toggleClass e containsClass dell’elemento.
- Possibilità di impostare stili CSS tramite l’oggetto style.
- Possibilità di impostare attributi dell’elemento o di sotto-oggetti interni all’elemento tramite il metodo setAttribute.
- Manipolazione tramite codice della struttura degli elementi, usando i metodi clone, appendChild, insertBefore e removeChild. L’array elements contiene tutti gli elementi figli di un determinato RemElem.
- Gestione del focus tramite i metodi focus e blur e i relativi eventi.
Contesto di esecuzione del codice di una sessione #
Alla luce degli esempi precedenti è importante comprendere che tutto il codice presente in un progetto Instant Developer Cloud sarà in funzione nel container che ospita l’applicazione. Negli esempi precedenti, ad esempio, il codice che gestisce l’evento onClick è in esecuzione nel server Node.js, non nel browser dell’utente.
Questa soluzione ha diversi effetti positivi:
- Tutto il codice applicativo, anche quello di gestione del front-end, è in grado di usare le risorse del back-end, quindi, ad esempio, può fare una query sul database.
- Non è necessario creare uno strato di webapi per far funzionare il front-end, quindi l’applicazione è più sicura oltre a richiedere molto meno tempo di programmazione.
- Il server opera sull’applicazione sempre in modalità push, quindi quando vengono rilevati eventi non derivanti dall’interfaccia utente, il server può comunque aggiornare il browser senza alcun intervento dell’utente.
È possibile usare Instant Developer Cloud anche per creare architetture più tradizionali, cioè lasciare in esecuzione nel cloud uno strato di webapi e sviluppare il front-end in modalità offline, cioè completamente in esecuzione nel browser o nel device. In questo caso il front-end ed il back-end potranno comunicare tramite webapi.
Il sistema di sincronizzazione di Instant Developer Cloud è in grado di convertire automaticamente l’architettura standard vista in precedenza in questo secondo tipo. Si consiglia quindi di utilizzare Instant Developer Cloud in modalità standard avendo comunque la possibilità di scegliere successivamente il tipo di architettura finale della propria applicazione.
Referenziare elementi dal codice della videata #
Come abbiamo visto in precedenza, il codice inserito all’interno di una videata può riferirsi alla sessione applicativa tramite la variabile app. È altresì possibile riferirsi alla videata attuale usando la variabile view, sempre definita all’interno degli script della stessa.
Sia la videata che tutti i suoi elementi possono riferirsi agli elementi contenuti, come proprietà dell’oggetto stesso. Ad esempio, nel caso della videata nell’immagine precedente è possibile riferirsi alla label di cui cambiare il testo tramite la seguente espressione:
view.IonStdPage.content.list.item.label
Per facilitare la scrittura del codice, l’editor di codice supporta la seguente sintassi: $<nome elemento>, quindi nel caso precedente è possibile scrivere semplicemente $label. Se la videata contiene più elementi con lo stesso nome, viene referenziato il “più vicino” allo script che si sta scrivendo, intendendo quello contenuto nel contesto più piccolo che contiene anche lo script stesso. Se ci sono più elementi con la stessa distanza, verrà selezionato il primo. Per controllare a quale elemento si riferisce una determinata espressione, utilizzare il menu contestuale dell’editor di codice, come mostrato nell’immagine seguente.
Videate come componenti #
Abbiamo visto che per definire l’interfaccia utente di una videata è necessario aggiungere gli elementi visuali che la compongono. Tali elementi possono corrispondere uno a uno con gli oggetti DOM del browser, ma possono rappresentare anche oggetti più complessi come mappe, grafici, slider, liste e così via. Abbiamo visto anche che è possibile estendere gli elementi disponibili importando il relativo codice JavaScript e definendo una classe di interfaccia.
Tuttavia in diverse occasioni è interessante poter definire nuovi componenti per aggregazione di quelli esistenti. Instant Developer Cloud supporta questa modalità di creazione di componenti in due modi:
- Tramite la definizione di template
- Rendendo una videata disponibile come componente di design time.
Uso dei template #
Un template è un insieme di elementi visuali che possono essere riutilizzati in contesti diversi. Viene definito inserendo una videata in una libreria personalizzata del progetto e poi attivando il flag design time dell’elemento che contiene il template. È necessario che la videata non abbia essa stessa tale flag attivo.
Nell’immagine seguente vediamo come esempio la lista AddressForm che è stata definita come template.
A questo punto è possibile utilizzare il template in ogni altra videata del progetto, come si vede nell’immagine seguente, semplicemente inserendo il template che appare nella lista degli elementi utilizzabili (pannello a destra).
Occorre notare, infine, che le istanze di template non rimangono collegate alla sua definizione. Modificando il template, le istanze esistenti non vengono modificate.
Usare una videata come un componente #
Come abbiamo visto, i template sono semplicemente un mezzo per inserire nelle videate gli elementi visuali più velocemente. Per ottenere davvero nuovi componenti per aggregazione di quelli esistenti, è disponibile un secondo meccanismo che consiste nell’attivare il flag design time a livello di videata invece che di elemento visuale.
Nell’immagine seguente vediamo che per la videata Smap (Static map) è stato attivato il flag design time. In questo caso l’intera videata diventa un vero e proprio componente riutilizzabile che viene istanziato come se fosse un elemento visuale e diventa parte della videata che lo contiene.
Poiché Smap è un componente completo, se le proprietà definite nella videata sono state attivate come design time esse diventano parte dell’interfaccia del componente. Inoltre supportano l’evento onChange che viene notificato quando il contenitore le aggiorna.
Notiamo infine l’evento onMapClick, inserito come metodo della videata di tipo evento. Anche questo evento, essendo stato definito come design time, diventerà parte dell’interfaccia del componente.
Vediamo quindi un esempio di utilizzo del componente Smap in una videata del progetto.
In questa immagine vediamo il componente Smap contenuto all’interno di una lista di card. Sulla destra possiamo notare che le proprietà definite come design time sono ora impostabili dall’IDE come quelle degli elementi visuali.
Inoltre è stato definito lo script che gestisce l’evento onMapClick, visto che esso è definito come evento disponibile a design time.
Notiamo infine che, a differenza dei template, quando si usa un componente basato su una videata si crea un’istanza della classe, quindi aggiornando la classe tutte le videate si aggiornano di conseguenza.
In sintesi, siccome le librerie sono facilmente trasportabili da un progetto ad un altro tramite la definizione di pacchetti, la possibilità di definire template e componenti per aggregazione permette di creare una serie di componenti facilmente riutilizzabili in tutti i propri progetti.