Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Ext.js: l'oggetto Grid - Opzioni avanzate

Rendere le tabelle editabili e inserire dati esterni
Rendere le tabelle editabili e inserire dati esterni
Link copiato negli appunti

Dopo aver effettuato una panoramica generale sulle griglie di Ext, eccoci finalmente ad appofondire la conoscenza di questo sorprendente oggetto Javascript.

Le possibilità di spostare le colonne, di cancellarle, aggiungerle o modificarne le dimensioni con un semplice drag & drop, sono caratteristiche che riusciamo ad ottenere quasi senza fatica dal nostro Ext.grid, come abbiamo visto, ma una tabella, nelle applicazioni di uso comune, spesso non si limita a esporre semplicemente dei dati. Capita infatti di dover fornire una maggiore usabilità delle informazioni.

In qualità di progettisti, infatti, ci dobbiamo ccostantemente porre il problema dell'usabilità e della possibilità di fruizione da parte dell'utente delle nostre applicazioni. Il problema dell'usabilità si pone quando il modello del progettista (ovvero le sue idee riguardo al funzionamento del prodotto, idee che trasferisce al design del prodotto stesso) non coincide con il modello dell'utente finale (ovvero l'idea che l'utente concepisce del prodotto e del suo funzionamento). Il grado di usabilità si innalza proporzionalmente all'avvicinamento dei due modelli (modello del progettista e modello dell'utente). Grazie ad Ext.js, anche senza profonde conoscenze in termini di design applicativo, riusciremo a fornire tabelle con un elevato grado di usabilità. Forniremo all'utente una possibilità di interazione immediata con il record, suddivideremo i dati in blocchi logici utili a rendere performanti le chiamate che vengono fatte al server e al database, minimizzando, grazie ai paradigmi Ajax, la quantità di dati che viaggiano dal nostro client al server.

Per fare tutto questo, Ext introduce molte caratteristiche che si possono associare alle griglie. In questo articolo vedremo gli oggetti DataReader, in particolare il JsonReader, il GroupingView, il CheckboxSelectionModel, il paging e le griglie editabili.

L'oggetto DataReader

L'oggetto Ext.DataReader è una classe base astratta per la lettura di informazioni strutturate da una fonte di dati. Questi vengono convertiti in un oggetto contenente Ext.data.Record che, come abbiamo visto nell'articolo precedente, sono composti da dati e metadati (informazioni utili a leggere le informazioni stesse, ad esempio il tipo di dato di una colonna) per l'uso da parte di un Ext.data.Store. Questa classe è destinata ad essere estesa e non deve essere utilizzata direttamente. Le implementazioni esistenti al momento sono l'Ext.data.ArrayReader, Ext.data.JsonReader e Ext.data.XmlReader. Nell'esempio visto nel primo articolo abbiamo visto un esempio di XmlReader, pertanto in questo vedremo il JsonReader.

JsonReader

È una particolare implementazione del DataReader. Anch'esso è una classe utile a creare un array di oggetti Ext.data.Record da una risposta Ajax che contiene un oggetto JSON.

Codice di esempio:

var Employee = Ext.data.Record.create([
    {name: 'firstname'},                  // Map the Record's "firstname" field to the row object's key of the same name
    {name: 'job', mapping: 'occupation'}  // Map the "job" field to the row object's "occupation" key
]);
var myReader = new Ext.data.JsonReader({
    totalProperty: "results",             // The property which contains the total dataset size (optional)
    root: "rows",                         // The property which contains an Array of row objects
    id: "id"                              // The property within each row object that provides an ID for the record (optional)
}, Employee);
 

Questo codice prende in pasto un oggetto JSON di questa forma:

{
    'results': 2,
    'rows': [
        { 'id': 1, 'firstname': 'Bill', occupation: 'Gardener' },         // a row object
        { 'id': 2, 'firstname': 'Ben' , occupation: 'Horticulturalist' }  // another row object
    ]
} 

Dall'esempio risulta chiaro quindi come una serie di Record di tipo Employee vengano restituiti dal JsonReader durante la lettura del'oggetto Json. Di conseguenza l'array di record verrà poi utilizzato dallo store della griglia per esporre i dati recuperati dal server.

GroupingView

Raggruppare i dati di una griglia è una delle tecniche più utili in termini di usabilità. Grazie ad Ext possiamo farlo con pochissime istruzioni. Vedremo come sia possibile scegliere per quali dati raggruppare le nostre infromazioni, anche a runtime, ovvero dopo che la griglia è stata renderizzata nella pagina. Il grouping che si ottiene è, in parole povere, simile al grouping delle mail in Outlook, dove possiamo scegliere se raggruppare per argomento, per data o per mittente. Vediamo un esempio:

var grid = new Ext.grid.GridPanel({
    // A groupingStore is required for a GroupingView
    store: new Ext.data.GroupingStore({
        reader: reader,
        data: xg.dummyData,
        sortInfo:{field: 'company', direction: "ASC"},
        groupField:'industry'
    }),

    columns: [
        {id:'company',header: "Company", width: 60, sortable: true, dataIndex: 'company'},
        {header: "Price", width: 20, sortable: true, renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
        {header: "Change", width: 20, sortable: true, dataIndex: 'change', renderer: Ext.util.Format.usMoney},
        {header: "Industry", width: 20, sortable: true, dataIndex: 'industry'},
        {header: "Last Updated", width: 20, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
    ],

    view: new Ext.grid.GroupingView({
        forceFit:true,
        // custom grouping text template to display the number of items per group
        groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
    }),

    frame:true,
    width: 700,
    height: 450,
    collapsible: true,
    animCollapse: false,
    title: 'Grouping Example',
    iconCls: 'icon-grid',
    renderTo: document.body
});

Rispetto al codice che abbiamo visto fino ad ora, possiamo notare che la differenza fondamentale risiede nella dichiarazione dello store: store: new Ext.data.GroupingStore; e nella proprieta' view della griglia: view: new Ext.grid.GroupingView. In quest'ultima notiamo la definizione di un template per l'header del gruppo, in maniera che vengano scritti quanti record appartengono a un gruppo e il nome del campo per cui stiamo raggruppando.

CheckboxSelectionModel

Esistono diverse utility che possono essere associate alle nostre griglie per aumentarne l'usabilità. Una su tutte è il CheckboxSelectionModel che ci permette di associare una prima colonna di checkbox per selezionare facilmente tutte o alcune righe della nostra griglia, a cui poi assoceremo un'azione multipla sui record.

Per creare un semplice esempio dobbiamo innanzitutto creare il CheckboxSelectionModel:

var sm = new Ext.grid.CheckboxSelectionModel();

Includere l'oggetto appena creato nel columnModel:

columns:[
sm,

{..... rest of your columns .....}

]

Fornire l'oggetto selectionModel come current selection model per la griglia grid. Per far ciò scriveremo la seguente istruzione nella lista delle proprieta' della griglia:

selMode: sm

Paging

Una griglia con paginazione deve avere un elemento lato server per eseguire la scomposizione dei dati in pagine.

Quale che sia il linguaggio utilizzato lato server e il database, l'importante è che venga restituito un oggetto Json con il numero di record totali, con i dati della pagina corrente e che sia il risultato di una selezione sul database limitata alla pagina in questione.

L'unica differenza nello Store è l'aggiunta di una proprietà totalProperty. Nel nostro esempio, si usa 'total', che arriva da uno nostro script lato server con il valore per il numero totale di righe:

var ds = new Ext.data.Store({
 
        proxy: new Ext.data.ScriptTagProxy({
            url: 'http://www.vinylfox.com/yui-ext/examples/grid-paging/grid-paging-data.php'
        }),
 
        reader: new Ext.data.JsonReader({
            root: 'results',
            totalProperty: 'total',
            id: 'id'
        }, [
            {name: 'employee_name', mapping: 'name'},
            {name: 'job_title', mapping: 'title'},
            {name: 'hire_date', mapping: 'hire_date', type: 'date', dateFormat: 'm-d-Y'},
            {name: 'is_active', mapping: 'active'}
        ])
 
    });

A questo punto bisogna aggiungere una barra di paging (primo, indietro, avanti, ultimo) alla parte inferiore del riquadro della griglia e il gioco è quasi fatto:

var gridFoot = grid.getView().getFooterPanel(true);
 
var paging = new Ext.PagingToolbar(gridFoot, ds, {
    pageSize: 25,
    displayInfo: true,
    displayMsg: 'Displaying results {0} - {1} of {2}',
    emptyMsg: "No results to display"
}); 

L'ultimo passo è quello di passare il primo limite di inizio e i parametri per caricare i dati:

ds.load({params:{start:0, limit:25}});

Griglie editabili

Le griglie editabili sono sicuramente l'approccio più interessante in termini di interazione e usabilità dei dati. Abbiamo creato un esempio pratico che potete scaricare da qui e che ho già utilizzato in un video per ICTV.

Un esempio pratico

Abbiamo collocato all'inizio della nostra pagina il contenuto dei dati della nostra tabella e messo in un Array. Questa contiene i dati seguendo un particolare ordine. Nel nostro caso ogni riga dell'array dei dati contiene rispettivamente il nome di un'attività, la sua data di inizio, la relativa scadenza, e uno stato che ci aiuta a capire se l'attività e in corso, pianificata o altro:

var myData = [
        ['Realizzare 2 video per code it','03/06/2008','23/06/2008','IN CORSO'],
	    ['Realizzare 3 articolo per HTML.it','23/06/2008','24/06/2008','PIANIFICATA'],
	    ['Procedere con il disegno delle applicazioni IPHONE','13/04/2008','23/05/2008','IN RITARDO'],
        ['Comprare un IPHONE','03/07/2008','23/07/2008','PIANIFICATA'],
	    ['Comprare MAC','04/07/2008','23/08/2008','PIANIFICATA'],
	    ['Scrivere lettera a Mario Rossi','09/06/2008','02/10/2008','PIANIFICATA'],
        ['Cercare ristorante per Barbara Bianchi','01/10/2008','23/12/2008','PIANIFICATA']
	];

Andiamo in seguito a programmare un SimpleStore per immagazzinare i dati contenuti nell'array. Lo store contiene dei campi, che contengono attributi di chiamati name e type. Questi servono per istruire la nostra tabella a capire se il contenuto di una determinata colonna sarà una data o un campo di testo normale o qualsiasi altro elemento siamo soliti incontrare nelle nostre pagine web:

var store = new Ext.data.SimpleStore({
        fields: [
           {name: 'attivita'},
           {name: 'inizio', type: 'date', dateFormat: 'd/m/Y'},
           {name: 'scadenza', type: 'date', dateFormat: 'd/m/Y'},
		   {name: 'stato'}
        ]
    });

Sempre seguendo questo schema possiamo notare come l'oggetto griglia sia composto dagli oggetti che descrivono le sue colonne, che sono composti dagli attributi che aiutano la griglia nel formattare dei dati particolari, includendo addirittura controlli specifici come bloccare l'inserimento di date che cadono nel week end o simili:

var grid = new Ext.grid.EditorGridPanel({
        store: store,
        region:'center',
        columns: [
            {id:'attivita',header: "Attività", width: 260, sortable: true, dataIndex: 'attivita',
			 editor: new fm.TextField({
					allowBlank: false
				})
			},
            {header: "Data Inizio", renderer: formatDate, sortable: true, dataIndex: 'inizio',
			 editor: new fm.DateField({
                format: 'm/d/y',
                minValue: '01/01/06',
                disabledDays: [0, 6],
                disabledDaysText: 'Nel week end non si lavora!'
				})
			},
            {header: "Data Scadenza", renderer: formatDate, sortable: true,  dataIndex: 'scadenza',
			 editor: new fm.DateField({
                format: 'm/d/y',
                minValue: '01/01/06',
                disabledDays: [0, 6],
                disabledDaysText: 'Nel week end non si lavora!'
				})
			},
            {header: "Stato", width: 160, sortable: true, dataIndex: 'stato',
			 editor: new fm.TextField({
               allowBlank: false
				})
			}
        ],
        stripeRows: true,
        title:'Le mie attività'
    });

L'editabilità della griglia è data dalla dichiarazione Ext.grid.EditorGridPanel e dall'attributo editor associato ad ogni colonna. In un editor inseriamo i campi che abbiamo visto negli articoli riguardanti i form e possiamo notare che questi dati possono essere anche validati, resi obbligatori o meno o inibiti, così come abbiamo imparato a fare con gli oggetti Form.

Conclusione

Il nostro viaggio sugli aspetti client di Ext sta volgendo al termine. Le componenti più importanti sono emerse e la loro composizione ci può portare a costruire già applicazioni relativamente complesse. Nei prossimi articoli affronteremo altre due componenti fondamentali di Ext: alberi e menu.

Ti consigliamo anche