Flex e Flash mettono a disposizione un componente particolarmente utile quando si tratta di mostrare dati tabellari, ovvero il componente DataGrid. Tale componente permette di mostrare una serie di dati ed eventualmente ordinarli in base ad una determinata colonna, inoltre è anche possibile offrire all'utente la possibilità di modificare i dati contenuti nelle varie celle della tabella.
In questo articolo vedremo come creare un'istanza del componente DataGrid, come popolarla sfruttando un DataProvider e come agire sulla tabella per modificarne l'aspetto e alcune opzioni, tutto questo utilizzando Actionscript 3 e Flash CS3.
Creare un'istanza del componente DataGrid
Per prima cosa avviamo Flash CS3 e scegliamo di creare un nuovo file Actionscript 3; apriamo quindi il pannello Componenti (Finestra -> Componenti oppure Ctrl+F7), dalla categoria User Interface selezioniamo il componente DataGrid e trasciniamolo sullo stage.
Il componente sullo stage apparirà come un quadrato bianco, in modo piuttosto scarno.
Se proviamo a portarci sul pannello Parametri noteremo come, a differenza della maggior parte degli altri componenti, il DataGrid non preveda le voci data e label da popolare manualmente; questo perché il DataGrid può prevedere un diverso numero di righe e colonne e i nomi dei campi sono personalizzabili, quindi imposteremo il contenuto della tabella tramite Actionscript.
Concludiamo le operazioni sullo stage dando al componente il nome istanza tabella.
È anche possibile creare un'istanza del componente tramite Actionscript, tramite il codice:
Listato 1. Crea un'istanza del componente
import fl.controls.DataGrid;
var tabella:DataGrid = new DataGrid();
addChild(tabella)
È però necessario che il componente sia presente almeno nella libreria del filmato Flash, altrimenti non verrà creato.
Popolare il componente DataGrid
Apriamo il pannello Azioni (Finestra -> Azioni oppure F9) e inseriamo il codice:
Listato 2. Popola il componente DataGrid
import fl.data.DataProvider;
// creiamo un oggetto DataProvider
var dati:DataProvider = new DataProvider();
// lo popoliamo con i campi "Nome" e "Cognome" e i rispettivi valori
dati.addItem({Nome:"Mario", Cognome:"Bianchi"});
dati.addItem({Nome:"Franco", Cognome:"Rossi"});
dati.addItem({Nome:"Giuseppe", Cognome:"Verdi"});
// diciamo al componente di usare il dataProvider "dati" come fonte di dati
tabella.dataProvider = dati;
Per prima cosa importiamo la classe fl.data.DataProvider, necessaria per impostare un DataProvider tramite Actionscript, quindi creiamo un nuovo oggetto di nome dati che popoliamo poi con alcuni dati: notiamo come Nome e Cognome saranno identificati dal DataGrid come nomi delle colonne, mentre i dati saranno presentati su diverse righe, come possiamo vedere in figura.
Possiamo notare come Cognome e Nome siano in ordine inverso rispetto a quanto indicato nel DataProvider: per essere sicuri che l'ordine delle colonne sia quello da noi desiderato possiamo sfruttare il comando addColumn del DataGrid, che come si può intuire aggiunge una colonna alla tabella e si rivela molto utile per mettere i campi nell'ordine desiderato e non avere risultati indesiderati, infatti ad esempio il codice:
Listato 3. Ordina le colonne
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
tabella.dataProvider = dati;
ordina le colonne in maniera decisamente poco intuitiva, come vediamo in figura.
Sfruttando invece il comando addColumn
, come nel codice seguente, ordineremo le colonne come desideriamo. Questo si rivela particolarmente utile ovviamente nel caso di tabelle con molti campi.
Listato 5. Ordina le colonne con addColumn
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
Il DataProvider può essere popolato in diversi modi: oltre alla compilazione diretta che abbiamo appena visto potremmo usare come fonte di dati un array, in questo modo:
Listato 6. Usa come fonte di dati un array
import fl.data.DataProvider;
// creiamo un array
var array_dati:Array = new Array()
// popoliamo l'array con diversi dati
array_dati.push({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
array_dati.push({Anni:34,Nome:"Franco",Cognome:"Rossi"});
array_dati.push({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
// creiamo un DataProvider basato sulla struttura dell'array
var dati:DataProvider = new DataProvider(array_dati);
Oppure ricavando i dati da una struttura XML, così:
Listato 7. Usa come fonte di dati una struttura XML
import fl.data.DataProvider;
var xml_dati:XML = <items>
<item Anni="51" Nome="Mario" Cognome="Bianchi" />
<item Anni="34" Nome="Franco" Cognome = "Rossi" />
<item Anni="27" Nome="Giuseppe" Cognome="Verdi" />
</items>
var dati:DataProvider = new DataProvider(xml_dati);
Sempre basandosi su una struttura XML, potremmo caricare i dati da un file esterno:
Listato 8. Usando una struttura XML carica i dati da file esterno
import fl.data.DataProvider;
var dati:DataProvider
// Carichiamo un file XML esterno
var file:String = "dati.xml";
var req:URLRequest = new URLRequest(file);
var uLdr:URLLoader = new URLLoader();
uLdr.addEventListener(Event.COMPLETE, analizza);
uLdr.load(req);
// quando è stato caricato lo analizziamo
function analizza(event:Event):void {
var ldr:URLLoader = event.currentTarget as URLLoader;
var dati_xml:XML = new XML(ldr.data);
// inseriamo i dati nel DataProvider
dati = new DataProvider(dati_xml);
// associamo il DataProvider alla tabella
tabella.dataProvider = dati;
}
Vi sono quindi svariate modalità per popolare un DataProvider e di conseguenza per popolare un componente DataGrid: l'importante è che alla fine il DataProvider contenga tutte le colonne e i dati che desideriamo mostrare all'utente.
Ridimensionare il componente DataGrid
Per ridimensionare un DataGrid possiamo agire sia impostando separatamente altezza e larghezza (usando le proprietà height e width) oppure tramite il comando setSize(larghezza,altezza). Quindi aggiungere al nostro codice o le righe:
tabella.width = 300
tabella.height = 100
oppure il comando
tabella.setSize(300,100)
Darà in entrambi i casi il risultato:
C'è un piccolo effetto indesiderato: se il ridimensionamento in larghezza non dà problemi, in altezza ci troviamo con una sorta di "buco", poichè le righe occupano meno spazio di quello impostato per la tabella.
C'è però un comando in grado di risolvere tutto, ovvero la proprietà rowCount.
Tale proprietà permette di impostare il numero di righe che il DataGrid deve mostrare e si occupa automaticamente di stabilire quanto sia lo spazio necessario; poichè il rowCount agisce solo sull'altezza sarà comunque necessario impostare la larghezza tramite la proprietà width. Ecco un esempio:
Listato 9. Inposta il numero di righe da mostrare
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
tabella.width = 300
tabella.rowCount = 3
Nota: la proprietà rowCount stabilisce quante righe rendere visibili, quindi nel caso in cui il numero di righe fosse maggiore a quello impostato nel rowCount verrà mostrata una barra di scorrimento verticale.
È interessante notare come la proprietà rowCount si basi sul numero di righe indipendentemente dalla loro dimensione, infatti, qualora avessimo delle righe più alte dell'impostazione usando rowCount saremo sempre sicuri di mostrarle integralmente. Proviamo ad esempio il codice riportato di seguito, dove tramite la proprietà rowHeight sono state impostate righe alte ognuna 80 pixel.
Listato 10. Imposta le righe in altezza
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
dati.addItem({Anni:21,Nome:"Davide",Cognome:"Beltrame"});
dati.addItem({Anni:45,Nome:"Valeria",Cognome:"Rossi"});
dati.addItem({Anni:71,Nome:"Virgilia",Cognome:"Corsinovi"});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
tabella.width = 300
tabella.rowHeight = 80
tabella.rowCount = 3
Il risultato sarà il seguente:
Un altro possibile utilizzo della proprietà rowCount è quello di mostrare sempre tutti i dati della tabella: per questo possiamo abbinare le proprietà rowCount e length, quest'ultima infatti restituisce il numero di righe che compongono la tabella.
Con il seguente codice la tabella avrà sempre un'altezza tale da mostrare tutte le righe impostate dal DataProvider.
Listato 11. Imposta l'altezza della tabella in base ai dati
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
dati.addItem({Anni:21,Nome:"Davide",Cognome:"Beltrame"});
dati.addItem({Anni:45,Nome:"Valeria",Cognome:"Rossi"});
dati.addItem({Anni:71,Nome:"Virgilia",Cognome:"Corsinovi"});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
tabella.width = 300
tabella.rowCount = tabella.length
Finora abbiamo preso in considerazione la possibilità di uno scrolling verticale, ma potrebbero esserci casi in cui la tabella abbia molte colonne e sia quindi necessario uno scrolling orizzontale per garantire una buona consultazione dei dati: il componente DataGrid mette a disposizione la proprietà horizontalScrollPolicy, da utilizzare come nel codice seguente:
Listato 12. Imposta lo scrolling orizzontale
import fl.data.DataProvider;
// importiamo la classe fl.controls.scrollPolicy
import fl.controls.ScrollPolicy;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
dati.addItem({Anni:21,Nome:"Davide",Cognome:"Beltrame"});
dati.addItem({Anni:45,Nome:"Valeria",Cognome:"Rossi"});
dati.addItem({Anni:71,Nome:"Virgilia",Cognome:"Corsinovi"});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
// impostiamo una larghezza tale da non contenere tutte le colonne
tabella.width = 100
// attiviamo lo scrolling orizzontale
tabella.horizontalScrollPolicy = ScrollPolicy.ON
tabella.rowCount = tabella.length
Il risultato sarà:
Impostare l'ordinabilità delle colonne
Il DataGrid, come impostazione predefinita, offre all'utente la possibilità di ordinare i dati in base ad ogni colonna raffigurata nella tabella, sia in ordine crescente che in ordine decrescente; la colonna ordinata e il relativo senso vengono evidenziati tramite una apposita freccetta in alto a destra nell'intestazione della colonna stessa.
È possibile impedire l'ordinamento di tutte le colonne oppure operare in maniera più selettiva e quindi lasciarne alcune ordinabili e altre no. Per agire sull'intera tabella è sufficiente la proprietà sortableColumns, che accetta come valori true (le colonne saranno ordinabili) e false (le colonne non saranno ordinabili), mentre per agire su una singola colonna è necessario usare il comando getColumnAt(numero), dove numero è un valore che parte da 0 e relativo alle colonne.
Nella nostra tabella di esempio potremmo rendere ordinabili i dati solo per la colonna "Anni", andando a disabilitare l'ordinamento per le prime due, ovvero le colonne 0 (Cognome) e 1 (Anni), in questo modo:
tabella.getColumnAt(0).sortable = false
tabella.getColumnAt(1).sortable = false
Un'altra opzione importante e impostabile per ogni colonna è il criterio di ordinamento della stessa: il problema più comune, ad esempio, è il fatto che dei valori numerici vengano ordinati come stringhe, generando di conseguenza degli errori. Prendiamo ad esempio il seguente codice:
Listato 13. Ordina la colonna degli anni in modo crescente
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi"});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi"});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi"});
dati.addItem({Anni:201,Nome:"Davide",Cognome:"Beltrame"});
dati.addItem({Anni:45,Nome:"Valeria",Cognome:"Rossi"});
dati.addItem({Anni:101,Nome:"Virgilia",Cognome:"Corsinovi"});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
tabella.width = 300
tabella.rowCount = tabella.length
Ordinando la colonna degli anni in maniera crescente, ci aspetteremmo che i valori partano da 27...ma se proviamo a farlo ecco cosa succede:
Questo avviene perchè l'ordinamento di default è di tipo testuale, di conseguenza "1" viene ordinato prima di "2" indipendentemente dalla lunghezza della stringa. Per evitare questo genere di errori va utilizzata l'opzione sortOptions, che permette di impostare secondo quale criterio ordinare ogni colonna; nel nostro caso basterà aggiungere al codice la riga
tabella.getColumnAt(2).sortOptions = Array.NUMERIC
Per far sì che gli anni seguano un ordinamento di tipo numerico e non di tipo testuale.
Rendere modificabili i dati
Secondo analogo principio, anche per quanto riguarda la possibilità di modificare i dati è possibile agire sull'intera tabella (DataGrid.editable) o su ogni singola colonna (DataGridColumn.editable), ne consegue che con il comando tabella.editable = true
andremo a rendere modificabili tutti i dati; mentre, per rendere modificabile solo la colonna "Anni", utilizziamo il codice:
tabella.editable = true
tabella.getColumnAt(0).editable = false
tabella.getColumnAt(1).editable = false
tabella.getColumnAt(2).editable = true
Notiamo come sia necessario impostare la tabella come modificabile, perchè in caso contrario l'impostazione tabella.editable = false
andrebbe e "sovrascrivere" l'editabilità delle singole colonne e nessuna di esse risulterebbe modificabile anche qualora l'avessimo impostata singolarmente come tale.
Ricavare la selezione di un dato
Aspetto importante del DataGrid è la possibilità di ricavare quale dato sia stato selezionato dall'utente: per ogni dato potremo accedere alle proprietà impostate come colonne (nel nostro esempio Nome, Cognome e Anni). Il procedimento è molto semplice: è sufficiente sfruttare l'evento CHANGE, associandolo ad una funzione che si occuperà di reperire i dati dell'elemento selezionato.
Listato 14. Ricava il dato selezionato dall'utente
tabella.addEventListener(Event.CHANGE ,cerca)
function cerca(evt:Event){
trace(evt.target.selectedItem.Nome)
trace(evt.target.selectedItem.Cognome)
trace(evt.target.selectedItem.Anni)
}
Teniamo presente che possiamo utilizzare anche dei dati "nascosti", per esempio è possibile inserire un campo nel DataProvider
ma poi non mostrarlo nel DataGrid; ad esempio con il seguente codice creiamo per ogni elemento un campo id che verrà ricavato solo al momento della selezione mentre non sarà visibile nella tabella poichè non è stata creata la colonna "id" con il comando addColumn.
Listato 15. Imposta per ogni elemento un dato id che non verrà visualizzato
import fl.data.DataProvider;
var dati:DataProvider = new DataProvider();
dati.addItem({Anni:51,Nome:"Mario",Cognome:"Bianchi",id:1});
dati.addItem({Anni:34,Nome:"Franco",Cognome:"Rossi",id:2});
dati.addItem({Anni:27,Nome:"Giuseppe",Cognome:"Verdi",id:3});
dati.addItem({Anni:201,Nome:"Davide",Cognome:"Beltrame",id:4});
dati.addItem({Anni:45,Nome:"Valeria",Cognome:"Rossi",id:5});
dati.addItem({Anni:101,Nome:"Virgilia",Cognome:"Corsinovi",id:6});
tabella.addColumn("Cognome")
tabella.addColumn("Nome")
tabella.addColumn("Anni")
tabella.dataProvider = dati;
tabella.width = 300
tabella.rowCount = tabella.length
tabella.addEventListener(Event.CHANGE ,cerca)
function cerca(evt:Event){
trace(evt.target.selectedItem.id)
}
Conclusione
Abbiamo visto alcune delle peculiarità del componente DataGrid, in particolare la versatilità offerta a livello di fonte di dati e le numerose possibilità di ridimensionamento e scrolling sia orizzontale che verticale, inoltre è stato trattato il procedimento per applicare particolari proprietà solamente ad una colonna piuttosto che all'intera tabella.
Le nozioni viste in questo articolo a livello di Actionscript 3 sono valide sia per il componente DataGrid offerto da Flash CS3 che per quello offerto da Flex. Flex 3 offre un componente addirittura più avanzato, chiamato appunto Advanced DataGrid e di cui si è accennato nell'articolo sulle novità di Flex 3; al momento non vi sono informazioni sull'eventuale integrazione di questo componente in Flash, tuttavia già con il normale DataGrid è possibile catalogare e rappresentare i dati in maniera semplice ed efficiente e si rivela quindi più che sufficiente per la maggior parte delle situazioni che richiedano l'uso di tabelle di dati.