La struttura degli elementi visuali che compongono un albero è mostrata nell’immagine seguente:

Il widget IdfTree può essere contenuto direttamente a livello base in una videata, se non sono previsti altri elementi, oppure può essere posizionato all’interno di qualunque altro elemento di tipo container, come ad esempio IonContent nel caso di pagina standard Ionic.
Facendo riferimento all’immagine precedente il primo elemento figlio dell’albero idfTreeCategories è categoryTreeNode un elemento di tipo IdfTreeNode (il nodo dell’albero) che rappresenta il primo livello dei dati. In esso verranno caricati i dati della datamap categoriesTreeDM. Un nodo può contenere un altro nodo, come vediamo nell’immagine qui sopra dove sotto il nodo categoryTreeNode è presente il nodo productTreeNode che visualizza i dati caricati dalla datamap innestata productsTreeDM. Questa struttura permette di caricare al primo livello dell’albero degli elementi categoria e all’interno di ogni categoria gli elementi prodotto relativi.
Dopo i nodi vediamo che sono presenti le datamap relative che forniscono ad ogni nodo i propri dati.
Aggiungendo un oggetto IdfTreeNode viene automaticamente aggiunta la datamap di caricamento dei dati il cui template è il nodo stesso come si vede nell’immagine più sotto. Il template rappresenta il modello visuale di un record della datamap quindi l’elemento che verrà ripetuto nella videata per ogni riga.

Un elemento IdfTreeNode può contenere altri elementi visuali che aggiungono funzionalità come bottoni, campi di input e immagini. Questo può essere utile per personalizzare il layout del nodo di un albero in modo da adeguarlo alle proprie esigenze ed uscire dallo schema standard di label, icon e badge per rappresentare un elemento, nel capitolo Layout personalizzato è illustrato un esempio esplicativo.
Nella barra delle proprietà del widget IdfTreeNode è possibile indicare quale campo del documento, sotteso alla datamap relativa, è la fonte dati per la label del nodo dell’albero nella proprietà Sorgente dati.

È possibile indicare un’icona per il nodo selezionandola tra quelle presenti nel progetto mediante la proprietà icon; oppure utilizzare un’immagine caricata nell’applicazione come risorsa di tipo immagine, facendo riferimento ad essa con $nomeRisorsa.Inoltre è possibile utilizzare la proprietà badge che verrà visualizzato sul nodo come nell’immagine più sotto evidenziata nel riquadro rosso, questa proprietà è normalmente impostata a runtime.
I valori label, icon e badge possono essere valorizzati a runtime nell’evento onRowComposition della datamap sorgente dati del nodo.
Nell’editor delle videate l’albero appare come nell’esempio seguente:

La parte superiore dell’albero contiene la toolbar con il bottone per collassare l’elemento.
Nella toolbar dell’albero viene visualizzata la proprietà Caption dell’elemento IdfTree.
Nell’esempio qui sopra è abilitata la multi selezione degli elementi dell’albero che si attiva mediante la proprietà ShowMultipleSelection.
Creazione e modifica di un albero #
Creazione di un albero #
Per iniziare ad utilizzare gli alberi è necessario importare il pacchetto FluidUI, che contiene la libreria IDFWidgets con le definizioni degli elementi che compongono gli alberi.
A questo punto è possibile inserire il componente IdfTree sia a livello di videata che di elemento container. Mediante l’utilizzo dei container con layout horizontal o vertical è possibile combinare elementi alberi e pannelli nella stessa videata.
Nell’immagine seguente possiamo vedere una videata con al suo interno un albero e dei pannelli in un layout composto da container e altContainer.

Albero affiancato ad un pannello mediante un container a layout horizontal
Subito dopo aver inserito nella videata il componente IdfTree, al quale automaticamente sono aggiunti un elemento IdfTreeNode e una datamap, viene selezionata la datamap del nodo. A questo punto è possibile indicare il tipo di documenti che verranno mostrati nel nodo dell’albero.
Come per ogni altra datamap è possibile utilizzare una query di caricamento dei dati, oppure specificare le proprietà e caricare i dati direttamente in memoria. La soluzione migliore e più flessibile è sempre quella di passare attraverso i documenti.
Per definire quale informazione visualizzare nella label del nodo dell’albero si imposta la proprietà Sorgente dati con il relativo campo della datamap come da immagine seguente.

L’informazione contenuta nella proprietà label può anche contenere codice HTML e in questo caso per farla interpretare correttamente dal framework occorre impostare a true la proprietà useHTML del nodo.
Oltre alla proprietà label esiste anche una proprietà badge che è possibile impostare a design time oppure a runtime utilizzando l’evento onRowComposition della datamap del nodo.
Nel codice qui sotto impostiamo il badge del nodo con il numero di prodotti contenuti in una categoria.
$categoriesTreeDM.onRowComposition = function(row, template)
{
$categoryTreeNode.badge = row.numberOfProducts;
};
È possibile attivare una visualizzazione compatta di un albero, in modo che occupi meno spazio in altezza sui nodi, impostando a true la proprietà compacted dell’elemento IdfTree.
Modifica di un albero #
Per aggiungere un ulteriore livello ad un albero è sufficiente inserire, sotto al nodo interessato, un altro elemento IdfTreeNode. L’aggiunta di un nodo sotto un altro nodo determina l’inserimento di una nuova datamap innestata sotto quella del livello precedente dell’albero come si vede nell’immagine seguente.

In questo modo è possibile realizzare strutture complesse a piacimento utilizzando elementi IdfTreeNode nidificati.
La proprietà label dei nodi dell’albero può essere personalizzata utilizzando gli stili inline degli oggetti IdfTree e IdfTreeNode per definire grassetto, colore di sfondo e tutte le altre proprietà di stile di un elemento visuale.
Naturalmente possono essere personalizzate anche le classi CSS dell’elemento IdfTree che è possibile trovare nella risorsa treeCSS della classe IdfTree della libreria IDFWidgets.
Al suo interno possiamo trovare la definizione di default delle variabili colore dei vari elementi dell’albero e tutte le classi CSS che lo configurano; Qui di seguito è riportato un esempio delle variabili di configurazione:
:root {
/* Toolbar */
--col-back-primary-tree: color-mix(in srgb, $primary 50%, black);
--col-fore-primary-tree: #ffffff;
/* Toolbar buttons, icons */
--col-back-secondary-tree: #ffffff;
--col-fore-secondary-tree: $primary;
--col-tree-back: #f8f8f8;
/***** Nodes *****/
--col-active-node-back: #e5e5e5;
--col-node-hover: #eeeeee;
--node-height: 32px;
--compact-node-height: 24px;
--col-focused-node-border: #d0d0d0;
}
Se per esempio vogliamo modificare l’altezza di tutti i nodi nella nostra applicazione possiamo semplicemente sovrascrivere la variabile –node-height nel CSS della nostra applicazione:
:root {
--node-height: 32px !important;
}
È necessario indicare la clausola !important per garantire la sovrascrittura della regola.
Layout personalizzato #
In alternativa all’utilizzo della label per visualizzare il contenuto di un nodo è possibile creare un proprio layout. Per disabilitare la visualizzazione della label di default occorre impostare a false la proprietà showLabel.
Per esempio se si vuole realizzare una struttura come quella nell’immagine seguente, dove abbiamo che un nodo è composto da: un bottone, un’immagine e due testi uno sotto l’altro, occorre procedere come descritto più in basso.

Per prima cosa si disabilita l’utilizzo della label di default mediante la proprietà Show label.
Quindi si deve realizzare una struttura come quella che vediamo nell’immagine seguente.

Qui, sotto l’elemento empTreeNodeBase, abbiamo il container cntNodeBase con layout horizontal che a sua volta ha tre container:
- cntButtonBase – che contiene un IonButtons con al suo interno un IonButton
- cntImageBase – che contiene un Image
- cntLabelBase – che contiene un IonLabel con al suo interno un IonText
A questi tre container è possibile associare l’evento onClick per far compiere specifiche azioni ad ognuno di essi. All’interno dell’evento è possibile fare riferimento ai dati della datamap mediante this.row.
In questo esempio è stata modificata l’altezza del nodo impostando height: 80px negli stili inline dell’elemento empTreeNodeBase per adeguare lo spazio alle dimensioni dell’immagine.
Alberi ricorsivi #
Per realizzare un albero ricorsivo, che naviga una struttura gerarchica di una tabella con legami padre figlio di cui non sappiamo in partenza il livello di profondità, dovremo utilizzare le datamap innestate ricorsive (vedere il manuale Datamap al capitolo Datamap ricorsive).
Se vogliamo realizzare l’albero della struttura dei legami tra i record della tabella Employees, che ha il campo ReportsTo che contiene l’id del proprio record padre, dobbiamo utilizzare la seguente struttura.

La datamap employeeDM ha come Tipo contenuto il documento Employee. Questo documento ha una collection figlia di documenti di tipo Employee legati dalla foreign key sul campo ReportsTo (il campo che realizza la relazione padre figlio).
La datamap childEmployeeDM ha come Tipo contenuto la collection figlia del documento Employee in questo modo sa esattamente quali record caricare e con quale chiave.Sulla datamap childEmployeeDM è impostata la proprietà Recursive a true.
La datamap di livello zero employeeDM che alimenta il nodo employeeTreeNode ha un filtro di caricamento che prende tutti i record della tabella Employees senza un padre (quelli con il campo ReportsTo vuoto). Questo lo realizziamo impostando il codice seguente nell’evento onLoad della videata.
$employeeDM.setFilter(App.NwindBE.Employee.ReportsTo, "!");
yield $employeeDM.load();
Una struttura ricorsiva di questo tipo viene creata automaticamente dall’ide di Instant Developer Cloud quando il documento utilizzato nella datamap del nodo ha una collection figlia di documenti del suo stesso tipo unica cosa da fare è scrivere il codice che filtra il livello base dell’albero come abbiamo visto poco sopra.