Sei sulla pagina 1di 43

Introduzione a Ext.

js
Ext.js (http://extjs.com/) è un framework Javascript utile a realizzare GUI complesse per web
application, ma non solo. Con Ext.js (da qui in avanti solo Ext) possiamo creare pagine con layout
avanzati anche se non possediamo particolari competenze CSS; possiamo agganciare funzionalità
AJAX di aggiornamento per le nostre interfacce; creare moduli wizard o textarea con testo enriched
(formattato come lo formatterebbe un programma di videoscrittura); agganciare le nostre web
application a ulteriori strumenti (MooTools, JQuery, Prototype, Google Gears e molti altri) in modo
da avere rapidamente software decisamente vicini alle applicazioni desktop con cui lavoriamo
quotidianamente.
L'elenco delle possibilità che ci apre la conoscenza di Ext potrebbe estendersi ben oltre le righe di
questo articolo, pertanto lo scopo di queste pagine sarà ristretto a fornire una panoramica di tutte le
potenzialità che questo tool ci offre. Cercherò di trasmettere l'entusiasmo che si prova nel
completare in pochi semplici passi le prime interfacce applicative, andando ben oltre i consueti
'Hello World' d'esordio di un manuale, rendendo così i lettori capaci di leggere e interagire con le
GUI Ext.
Creeremo insieme, in pochi minuti, una home completa per un prodotto o un sito, utilizzando Ext.
Sfrutteremo poi lo stesso esempio per andare avanti nei prossimi articoli, in modo da arrivare a
realizzare la nostra riserva applicativa personale. (ecco l'esempio).

Gli standard e la licenza


La programmazione delle pagine che utilizzano Ext segue gli standard ormai largamente diffusi
nell'ambiente Web 2.0. Pertanto gli script Javascript seguono le tecniche dell'OOP (Object Oriented
Programming), si fa largo uso di tecniche AJAX, di lettura e gestione DOM e di oggetti JSON. Ciò
nonostante, per riuscire ad avere fin da subito risultati più che soddisfacenti, non è necessario avere
delle profonde conoscenze di Javascript, ma basta procedere con una logica semplice nelle proprie
interfacce. Una volta compresa la forma con cui vengono costruiti pannelli e finestre, si riuscirà
facilmente a creare pagine e applicazioni complesse e pulite. Le conoscenze in ambito DHTML e
CSS sono utili, ma non indispensabili, dato che Ext provvede da sé a collocare e gestire in maniera
ordinata i diversi layer che compongono la nostra pagina.
Le varietà di GUI che possiamo realizzare è pressoché infinita, come abbiamo detto all'inizio di
questo articolo. Possiamo comporre tra loro tutti gli elementi che siamo soliti utilizzare nelle
applicazioni desktop, nessuno escluso, e forse qualcosa di più. Abbiamo: menu, tab, accordion,
pannelli, finestre, form, griglie, barre di splitting, toolbar, slider, status bar, progress bar, message
window, tree. Sfruttare layout, utilities sugli oggetti e molto altro ancora. Proseguendo nella lettura
di questa introduzione a Ext, vedremo esempi che ci sorprenderanno per la loro semplicità e
completezza.
Un tool indispensabile nella creazione di pagine HTML che sfruttano framework Javascript di
ultima generazione è FireBug. Il codice che viene utilizzato negli script Ext è pulito, comprensibile
e privo di eccezioni. Ext è (come MooTools e altri software simili) in grado di guidare il
programmatore nella creazione di interfacce prive di errori che FireBug traccerebbe.
Un codice pulito, la ricchezza di interfacce proposte, la completa compatibilità con tutti i browser e
con gran parte degli altri framework Javascript attualmente in distribuzione hanno reso Ext uno
strumento adottato da grandi gruppi per fornire una rich client interface alle proprie componenti.
Vediamo quindi in circolazione ottime soluzioni PHP, Coldfusion, o per il recente e già largamente
diffuso AIR di Adobe; ma soprattutto meritano menzione l'adozione di GWT di una interfaccia
basata su Ext e la facilità con cui si possono integrare applicazioni Ext con Google Gears. Negli
articoli che seguiranno questa prima introduzione entreremo nel dettaglio di ogni soluzione in modo
da fornire il lettore di un bagaglio di conoscenze utili a scegliere la migliore delle soluzioni a
seconda delle architetture che si troverà di fronte.
Prima di passare all'esempio pratico è buona norma leggere le licenze dei prodotti open source che
si vanno ad utilizzare. Nella sua nuova release (la 2.1) , Ext è passato alla versione GPL 3. Bisogna
pertanto pensare che per sviluppare prodotti open source o per scopi personali non si ha l'obbligo di
acquisto del framework, ma basta citarne l'utilizzo. Per poter inserire Ext in prodotti che
commercializziamo dobbiamo provvedere all'acquisto della libreria, tenendo comunque conto che il
costo è veramente molto ridotto rispetto al servizio di assistenza e all'ausilio nello sviluppo che ci
viene offerto.

Passiamo ai fatti
Ormai siamo curiosi di andare avanti e vedere quanto di ciò che abbiamo detto fino ad ora
corrisponde al vero. Pertanto andremo sul sito Ext e visiteremo la sezione Download. Qui potremo
decidere se scaricare subito Ext.js completo di sorgenti, esempi e documentazione (scelta che
raccomando ai newbie), o se passare alla costruzione del nostro personale pacchetto Ext. In ogni
caso consiglio di visionare quanto meno la possibilità di costruirsi il proprio pacchetto, in quanto è
interessante vedere e lasciarsi ispirare dal wizard di download costruito tramite Ext stesso. Oltre alle
due versioni di download troviamo un terzo utile link: la documentazione Ext basata su AIR. Come
anticipato prima, avremo modo di vedere più in profondità applicazioni complete basate su Ext, ma
già questa documentazione da poter visionare offline fornirà ai lettori più curiosi e impazienti, la
possibilità di vedere come risultano gradevoli le applicazioni Ext/AIR.
Ora abbiamo Ext sul nostro pc e, attenendoci ai limiti e ai propositi di questo articolo, vogliamo
finalmente vedere quanto sia realmente semplice e quali sono le possibilità di questo tool senza, per
il momento, considerare architetture complete di server side. Andiamo quindi a visionare la
directory examples. Qui troviamo esempi che soddifano le nostre esigenze, in quanto partiamo da
semplici pannelli a web os senza troppa difficoltà. Ma per prendere possesso dello strumento che
abbiamo tra le mani dobbiamo cominciare a scrivere qualche riga che ci dia la soddisfazione
iniziale di un'interfaccia di media complessità e ci induca a continuare.
Creiamo una cartella allo stesso livello di dove abbiamo posizionato la cartella 'ext'. Inseriamo una
pagina di nome esempio.html e apriamo un qualsiasi editor di testo dove trascriveremo il codice
HTML che segue:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>EXAMPLE 1. SIMPLE EXT GUI...</title>
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css"
/>
<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>
</head>

<body>
<div style="width:100%;height:100%;">
<div style="width:50%;background:#9e9efe;">
<h1>BANNER DEL MIO PRODOTTO</h1></div>

<div id="content" ></div>


</div>

<script type="text/javascript" src="js/esempio.js"></script>


</body>
</html>

Se dovessimo pensare di costruire una home page senza scrivere una riga di CSS, che sia gradevole,
che funzioni su ogni browser, che presenti quattro tab e una barra di navigazione o di news che
goda di funzionalità di close and expand, potremmo pensare di impiegare almeno mezza giornata di
sviluppo e debugging. Eppure nelle poche righe che abbiamo appena scritto abbiamo già messo
tutto quello che serve. Gran parte del lavoro è infatti svolto da Ext e dalla sua capacità di gestire in
maniera pulita il codice Javascript non intrusivo. Pertanto, aver incluso la terna minima per
sviluppare con Ext (ext-all.css, ext-base.js, ext-all.js) ci aiuta ad impostare la nostra pagina perché
possa usare a pieno le potenzialità del framework.
Nelle ultime righe del nostro codice HTML abbiamo istruito il browser perché vada a leggere il
codice Javascript che si trova nel file js/esempio.js. Creiamo quindi una cartella 'js' dentro alla
cartella in cui abbiamo inserito il file esempio.html, e inseriamo al suo interno un file esempio.js.
Il codice che scriveremo nella nostra pagina è reperibile qui. Le righe che, per questa volta,
analizziamo a fondo, sono solo queste:
var tabs = new Ext.TabPanel({
region: 'center',
margins:'3 3 3 0',
activeTab: 0,
defaults:{autoScroll:true},
bodyStyle:"background:#efefff",

items:[
{
title: 'Primo tab',
bodyStyle:"background:#efefff",
layout:'fit',
html: '<div>contenuto primo pannello</div>'
},{
title: 'Secondo tab',
bodyStyle:"background:#efefff",
layout:'fit',
html: '<div>contenuto secondo pannello</div>'
},{
title: 'Terzo tab',
bodyStyle:"background:#efefff",
layout:'fit',
html: '<div>contenuto terzo pannello</div>'
},{
title: 'Quarto tab',
bodyStyle:"background:#efefff",
layout:'fit',
html: '<div>contenuto quarto pannello</div>'
}]
});

Come vedete questo è normalissimo codice JSON che Ext interpreta e rende in maniera piuttosto
intuitiva. Andiamo a leggere quanto abbiamo descritto nell'oggetto tabs. La variabile tabs conterrà
un pannello adatto a mostrare ogni suo elemento come una tab/scheda (Ext.TabPanel).
Questo contenitore di tab sarà posizionato nella regione centrale di un pannello che avrà un layout
di tipo BorderLayout (analizzeremo nei prossimi articoli i layout). Abbiamo descritto i margini che
dovrà mantenere tabs, nella pagina, e istruito il browser perché renderizzi la prima tab come attiva
(activeTab:0).
Abbiamo descritto alcune caratteristiche grafiche delle nostre tab e poi abbiamo inserito
direttamente nell'array items, le quattro schede e i relativi codici HTML, con layout 'fit', in modo
che il contenuto della tab riempia tutta l'area a disposizione. Il risultato è il seguente.
Figura 1 - Screenshot dell'esempio

Concludendo
Abbiamo rispettato il nostro obiettivo e realizzato fin da subito qualcosa che va oltre i classici Hello
World degli inizi. Nei prossimi articoli impareremo a applicare diversi temi e colori alle nostre
applicazioni, a leggere le API e usare la localizzazione, a sfruttare al meglio la community, i plugin
e gli extra e a progettare le nostre GUI come fino ad ora il web non ci aveva mai concesso di fare.

Ext.js, temi e layout


Dopo aver effettuato una rapida panoramica su Ext nell'articolo precedente, possiamo finalmente
diventare operativi e affrontare due argomenti che ci serviranno a progettare al meglio le nostre
interfacce fin da subito: temi e layout.
Lo scopo di questo articolo consiste nell'aiutare i lettori a liberarsi dell'annoso problema di come
integrare stili differenti per ogni utente, o di come organizzare i contenuti delle proprie pagine in
modo che siano cross-browser.
Fino a pochi mesi fa (nel mondo informatico, ormai, pochi mesi sono un anno), quando Ext e
framework simili non erano diffusi, non era semplice esporre i contenuti delle nostre pagine
applicando stylesheet differenti, o rendere i nostri utenti capaci di poter scegliere il tema di colori e
di immagini che preferivano per personalizzare la propria navigazione. Ora invece impareremo che
possiamo scegliere un set di temi che ci aggradano o crearne facilmente di nuovi e rendere il nostro
sito o la nostra applicazione più vicini alle esigenze di chi le utilizza in pochissimo tempo.
Oltre a quello della personalizzazione, poi, si presentava costantemente il problema
dell'organizzazione dei contenuti in maniera professionale e cross-browser, senza dover realizzare
stylesheet ad hoc per ogni browser o senza scrivere centinaia di righe Javascript per identificare il
browser che sta mostrando una determinata pagina.

Un tema, cos'è e come si applica


Nelle interfacce Ext, prende il nome di Xtheme l'aggregazione di stylesheet e immagini utili a
cambiare l'aspetto di pannelli, finestre, griglie e quant'altro sia presente nella nostra applicazione.
Ext viene rilasciato con il suo caratteristico layout azzurro (default) e con un altro grigio chiaro
(xtheme-gray). Per comprendere al meglio in cosa consista un tema e come lo si applichi, partiremo
da una semplice interfaccia e l'arricchiremo della possibilità di scegliere quale tema si preferisce.
Come semplice GUI di partenza riprendiamo l'esempio della volta scorsa, visibile qui e scaricabile
qui.
Alla fine dell'articolo, il lettore sarà in grado di scrivere e personalizzare interfacce come quella in
questo esempio.

Dove si trovano i file degli Xtheme


L'interfaccia che avevamo costruito viene esposta con il default-Xtheme. Se esploriamo il file
system in cui si trova la nostra directory Ext, troviamo “resources”, una delle directory più
importanti del framework. Dentro a “resources” abbiamo due cartelle che aiutano i lettori più
curiosi a capire come sono strutturati i themes: "css" e "images". Dentro a "css" troviamo tutti i file
di stylesheet che vengono inclusi da Ext per la visualizzazione default, tramite ext-all.css. Oltre a
questi troviamo i file xtheme-*.css che contengono le informazioni utili a cambiare lo stile del
nostro applicativo. Come abbiamo detto precedentemente, quindi, nella versione base troviamo solo
xtheme-gray.css. Se guardiamo dentro alla directory "images", troviamo una serie di cartelle
corrispondenti ai diversi xtheme presenti nella nostra installazione; nel caso della versione base di
cui stiamo parlando avremo solo due directory: "default" e "gray". Qui troviamo il set di immagini
che occorre ai file di stylesheet per modificare l'aspetto dei vari applicativi.

Aggiungiamo un Xtheme-selector
Rinominiamo il nostro file esempio.html dell'articolo precedente in theme.html e il suo Javascript in
theme.js. Per rendere la nostra pagina capace di cambiare aspetto, dovremo inserire una finestra o
una semplice combo box che ci aiutino a scatenare l'evento di scelta del tema da parte dell'utente.
Non avendo visto gli elementi form di Ext o le Window (che analizzeremo nei prossimi articoli),
procederemo in maniera ibrida e immediata creando del codice HTML che faremo interpretare da
Ext in modalità non-obtrusive (il Javascript non-obtrusive è, in poche parole, codice di scripting
applicato una volta che il DOM della pagina è stato creato, in maniera da lasciare pulita la nostra
pagina HTML e scorporare lo strato della logica da quello della visualizzazione, secondo i più
moderni e funzionali pattern di sviluppo).
Pertanto procederemo con la creazione di una semplice zona (nell'esempio è il div con
id="exttheme") che conterrà successivamente una combo box all'interno del nostro file HTML
di esempio:
<div style="width:100%;height:100%;" >

<div id="content"></div>
</div>
<div id="exttheme" style="float:left"></div>

Rendere intelligente la combo box e applicare i temi


Ora che abbiamo una combo box, la rendiamo ‘intelligente', attraverso il nostro file di scripting
Javascript. Pertanto aggiungeremo il seguente codice:
var themeData = new Ext.data.SimpleStore({
fields: ['display', 'value'],
data: [
['Default (Blue)', ''],
['Gray', '../ext/resources/css/xtheme-gray.css']
]
});
comboTheme = new Ext.form.ComboBox({
store: themeData,
renderTo:'exttheme',
displayField:'display',
typeAhead: true, mode: 'local',
triggerAction: 'all',
selectOnFocus:true,
resizable:false,
listWidth: 230,
width: 230,
valueField: 'value',
value: '' });

comboTheme.on('select',
function(combo){
Ext.util.CSS.swapStyleSheet('theme', combo.getValue());
}
, this);

Lanciando in un qualsiasi browser il file theme.html vedremo la nostra GUI a schede, con una
combobox che ci permette di cambiare a runtime tra lo stile grigio chiaro e quello blue di default
come in questa pagina.

Come si realizzano e dove si possono scaricare i temi


Personalizzando le directory che abbiamo visto prima di iniziare a creare il nostro esempio,
possiamo realizzare nuovi temi abbastanza velocemente, ma se le capacità grafiche dovessere venir
meno ai nostri progetti, possiamo contare sulla community Ext e sui thread aperti nella sezione
‘plugin e extra'. Ad esempio, sottoscrivendo il seguente topic potremo essere sempre aggiornati sui
nuovi xthemes in condivisione nel forum. I themes saranno sempre disponibili in file zip che
contengono una cartella "css" e una "images", in maniera che sovrascrivendo queste cartelle a
quelle del nostro file system Ext, avremo i nuovi themes. Questa pratica di sovrascrittura in
"resources", è valida anche per plugin ed esempi, in questo modo familiarizzeremo con le nuove
funzionalità e installazioni senza compromettere mai né il nostro codice, né il core system di Ext.

Cosa sono i layout


Risolto il problema della personalizzazione passiamo a quello dell'organizzazione dei contenuti. Ext
ci viene incontro in questa complessa problematica con un semplice attributo chiamato appunto
‘layout' che possiamo utilizzare nella definizione dei nostri pannelli. In pratica: immaginiamo di
voler costruire un layer con titolo ‘UNO' che contiene due elementi ‘uno.uno' e ‘uno.due', che si
mostrano alternandosi a fronte del click sul loro titolo. Per far questo dovremmo scrivere svariate
righe di Javascript e di CSS, tenendo conto del browser e della versione, etc, etc.; con Ext basterà
scrivere:
var panelUNO = new Ext.Panel({
title:'UNO',
layout:'accordion',
items: [
new Ext.Panel({title:‘uno.uno',html:'primo'}),
new Ext.Panel({title:‘uno.due',html:'due'})
]
});
E avremo il nostro pannello cross-browser e con i suoi dinamismi già pronti, semplicemente grazie
alla riga con scritto: layout:'accordion'.
I layout disponibili in Ext sono diversi e coprono tutte le esigenze che possono emergere in ambito
web e di disegno applicativo. Il sito di Ext ci viene in soccorso grazie a un esempio (presente anche
nel file system del pacchetto che scarichiamo dal web) chiamato layout-browser. Qui possiamo
vedere pressoché tutti i layout disponibili e una valida applicazione che utilizza a sua volta un
layout di tipo border.
In breve possiamo riassumere i layout più utili in questo elenco:
• Absolute: i contenuti hanno una posizione fissa nella pagina
• Accordion: i contenuti sono in una lista con caratteristiche di apertura del pannello corrente
e chiusura degli altri.
• Border: i contenuti possono essere collocati in zone (nord, sud, est, ovest, centro)
• Card: i contenuti si alternano a seconda di eventi (ad esempio un wizard).
• Column: i contenuti sono organizzati in colonne
• Fit: i contenuti occupano tutta la pagina (è il layout di default)
• Form: i contenuti sono adatti ad essere presentati in forma di modulo form
Come sempre, un esempio ci verrà in aiuto.

Estendiamo l'esempio con un layout per ogni tab


Copiamo il nostro esempio dei temi in un altro file di nome layout.html e iniziamo a lavorare su
quello. L'HTML rimarrà uguale e identico, tranne il Javascript che viene incluso, che non sarà più
theme.js ma layout.js, in modo da tenere i nostri due esempi separati.
Estendiamo i diversi contenuti HTML che avevamo settato nell'attributo ‘html' dei vari tab,
aggiungendo l'attributo layout e i contenuti che vogliamo esporre. Otterremo un codice simile a
questo:
items:[{
title: 'Io contengo dei pannelli accordion',
frame:true,layout:'accordion',
items: [
new Ext.Panel({title:'Primo accordion',frame:true,
html:'Contenuto del primo accordion'}),
new Ext.Panel({title:'Secondo accordion',frame:true,
html:'Contenuto del secondo accordion'}),
new Ext.Panel({title:'Terzo accordion',frame:true,
html:'Contenuto del primo accordion'}),
new Ext.Panel({title:'Quarto accordion',frame:true,
html:'Contenuto del secondo accordion'})
]
},{
title: 'Io contengo tre pannelli con layout border',
frame:true, layout:'fit',layout:'border',
items: [
{title: 'Footer',region: 'south',frame:true,
html:'Contenuto del pannello di sotto'},
{title: 'Navigation',region:'west',frame:true,
html:'Contenuto del pannello di sinistra'},
{title: 'Main Content',region:'center',
frame:true,collapsible:false,
html:'Contenuto del pannello centrale'}
]
},{
title: 'Io contengo un esempio di Card layout',
frame:true,
id:'card-panel',
layout:'card',
activeItem: 0, // index or id
bbar: ['->', {id: 'card-prev',
text: '« Precedente',
handler: cardNav.createDelegate(this, [-1]),
disabled: true},{id: 'card-next',
text: 'Successivo »',
handler: cardNav.createDelegate(this, [1])
}],
items: [{id: 'card-0',html: 'Contenuto del primo pannello!'},
{id: 'card-1',html: 'Contenuto del secondo'},
{id: 'card-2',html: 'Terzo pannello!'}]
}]

L'esempio completo è visibile in questa pagina.


È anche disponibile un pacchetto zip contenente tutto quanto visto nel corso dell'articolo.

Conclusioni e anticipazioni
Con questo articolo, abbiamo voluto fornire una panoramica su temi e layout e due esempi completi
e funzionanti che possono essere riutilizzati per i propri siti. In questo abbiamo preso ulteriormente
confidenza con la struttura JSON tipica delle strutture Ext, inoltre siamo pronti ad affrontare nei
prossimi articoli l'utilizzo più approfondito degli elementi che compongono le interfacce Ext.

Ext.js: il componente Panel


Abbiamo conosciuto Ext e abbiamo intravisto le sue potenzialità; abbiamo steso le basi per
superare i primi due grandi ostacoli: impaginazione e personalizzazioni; ora possiamo cominciare a
sviluppare tutto ciò che ci viene in mente o ci viene richiesto. Per far questo abbiamo bisogno di
conoscere uno ad uno gli elementi che compongono la nostra libreria e metterli nella classica
cassetta degli attrezzi per poi poter essere capaci di scegliere lo strumento giusto a seconda
dell'applicazione che stiamo sviluppando.
Lo scopo di questo articolo in due parti è quello di introdurre l'utilizzo degli oggetti Ext.Panel ed
Ext.Window. Alla fine di questi due articoli, il lettore sarà in grado di stabilire quale dei due oggetti
è più consono ai propri scopi, disegnare interfacce che contengono più Panel e Window,
personalizzare esempi che assomigliano a complesse formattazioni di pagine di giornale o creare
semplici motori che generano Window simili a post-it.

Object Oriented ed Ereditarietà


Le componenti Ext, come abbiamo già detto nei precedenti articoli, sono molte e tutte disegnate con
un orientamento gerarchico ad oggetti. L'oggetto più utile alla base della catena di ereditarietà Ext è
il Panel.
Per chi è pratico di programmazione orientate agli oggetti (Java, .NET ad esempio), è facile
intravedere le analogie con oggetti tipici della programmazione desktop (Swing / SWT).
Per chi non conoscesse la programmazione OO (Object Oriented) consigliamo innanzitutto la
lettura di qualche pagina di questo articolo su HTML.it: Pensare Object Oriented; inoltre possiamo
semplificare molto i concetti che compongono questa utile tecnica di programmazione rapportando
il nostro codice al mondo reale. Tutto cio' che ci circonda (il foglio o il monitor su cui stiamo
leggendo queste righe) sono particolari istanze di una generica classe Oggetto. Quando diciamo
quindi che Oggetto è un'entità astratta, intendiamo appunto questo: un oggetto può essere esteso ed
istanziato in qualsiasi cosa. I concetti di ereditarietà tra oggetti si inseriscono in questo esempio se
si pensa che il foglio su cui stiamo leggendo è un particolare foglio, figlio dell'oggetto Carta che a
sua volta è figlio dell'oggetto Materiali e così via. Diversi fogli (un A4, una carta da regalo, un post-
it) sono specializzazioni di Carta. Per chiudere questa breve carrellata esemplificativa, il foglio che
abbiamo in mano è un'istanza che identifica esattamente il foglio che stiamo reggendo, con i suoi
attributi che lo diversificano e lo rendono unico rispetto a un altro foglio.

Gli oggetti in Ext


Tornando ad Ext, quindi, leggiamo insieme l'albero genealogico dell'oggetto che ci interessa per
comprendere a pieno le sue proprietà. Ogni oggetto deriva da una componente astratta generica
chiamata Observable. Questa equivale all'oggetto più astratto che possiamo immaginare e che viene
utilizzato come base per costruire altri oggetti. Per agganciarci al nostro esempio, pensiamo al
seguente codice:
Foglio = function(name){
this.name = name;
this.addEvents({
"stampa" : true,
"archivia" : true,
"straccia" : true
});
}
Ext.extend(Foglio, Ext.util.Observable);

Continuando la lettura genealogica del nostro oggetto, incontriamo quella che è la base per tutte le
interfacce grafiche Ext: l'oggetto Component.
Ogni Component possiede un attributo xtype, che è il suo Ext-specific type name, e i relativi
metodi per identifcarlo: getXType e isXType.
Di seguito una lista degli xtypes validi:
xtype Class
box Ext.BoxComponent
button Ext.Button
colorpalette Ext.ColorPalette
component Ext.Component
container Ext.Container
cycle Ext.CycleButton
dataview Ext.DataView
datepicker Ext.DatePicker
editor Ext.Editor
editorgrid Ext.grid.EditorGridPanel
grid Ext.grid.GridPanel
paging Ext.PagingToolbar
panel Ext.Panel
progress Ext.ProgressBar
propertygrid Ext.grid.PropertyGrid
slider Ext.Slider
splitbutton Ext.SplitButton
statusbar Ext.StatusBar
tabpanel Ext.TabPanel
treepanel Ext.tree.TreePanel
viewport Ext.Viewport
window Ext.Window

Toolbar components
toolbar Ext.Toolbar
tbbutton Ext.Toolbar.Button
tbfill Ext.Toolbar.Fill
tbitem Ext.Toolbar.Item
tbseparator Ext.Toolbar.Separator
tbspacer Ext.Toolbar.Spacer
tbsplit Ext.Toolbar.SplitButton
tbtext Ext.Toolbar.TextItem

Form components
form Ext.FormPanel
checkbox Ext.form.Checkbox
combo Ext.form.ComboBox
datefield Ext.form.DateField
field Ext.form.Field
fieldset Ext.form.FieldSet
hidden Ext.form.Hidden
htmleditor Ext.form.HtmlEditor
label Ext.form.Label
numberfield Ext.form.NumberField
radio Ext.form.Radio
textarea Ext.form.TextArea
textfield Ext.form.TextField
timefield Ext.form.TimeField
Trigger Ext.form.TriggerField

Risaliamo ancora la catena che ci porterà al nostro oggetto e incontriamo BoxComponent, una
specializzazione di Component. è la classe base per ogni tipo di Ext.Component che usa contenitori
che prendono il nome di box, ovvero forme che contengono HTML.
BoxComponent fornisce automatismi per la modellazione dei box come il dimensionamento o la
posizione. Tutti gli oggetti che contengono HTML devono essere figli (sottoclassi) di
BoxComponent in modo che le loro proprietà siano congrue e convivano con gli altri box nel
momento in cui andremo a nidificarli uno dentro l'altro per poter ottenere i layout più disparati, utili
ai nostri scopi.
Dal nonno, arriviamo finalmente al padre del nostro tanto atteso oggetto, ovvero: Container. Di
default, i Containers usano gli schemi di layout che abbiamo introdotto nei precedenti articoli e che
prendono il nome di ContainerLayout. In questo modo le componenti che vanno a nidificarsi l'una
nell'altra sfruttano i meccanismi di collocazione nella pagina e possiamo appenderli uno dopo l'altro
all'interno del Container, senza preoccuparci delle dimensioni o della convivenza cross-browser
degli elementi.
Arriviamo così, attraverso gli avi, alla componente che da oggi useremo ed estenderemo fino a farla
diventare il punto di partenza di ogni nostro disegno di interfaccia: il Panel.

La componente più semplice: il Panel


La classe Ext.Panel, estende Ext.Container ed è alla base di ogni altro tipo di interfaccia. I suoi
attributi e le sue peculiarità ci aiutano a identificare il Panel con un ipotetico div/layer in cui
suddividere le pagine dei nostri siti e delle nostre applicazioni.
Le potenzialità del Panel si intravedono dalla lista delle sue sottoclassi, ovvero: TabPanel, Tip,
Window, FieldSet, FormPanel, GridPanel, TreePanel. Questi sono tutti oggetti che esamineremo,
uno per uno, nei prossimi articoli e che ci consentono di strutturare i nostri dati nella forma più utile
per ogni tipologia di interazione con l'utente.
Gli attributi di un Panel
Gli attributi che può assumere un panel sono veramente numerosi. Non possiamo elencare
all'interno di questo articolo, per motivi di spazio, tutte le caratteristiche del nostro Panel ma
provvederemo ad analizzare quelli che riusciremo ad incontrare attraverso il nostro classico
esempio.
Immaginiamo che ci venga commissionata una pagina di un ipotetico giornale come quello in
figura.
Figura 1 - Screenshot dell'esempio da realizzare

Impaginarla in questa maniera, magari rendendo dinamici i contenuti, rimanendo cross-browser e


costruendo l'architettura in modo che sia scalabile, ovvero facilmente estendibile avrebbe richiesto
esperti CSS e di sviluppo, oltre che un duro lavoro di analisi di compatibilità tra i vari browser.
Grazie ad Ext, una volta disegnata l'architettura della nostra pagina, possiamo identificare il layout
più appropriato al nostro scopo e suddividere la nostra pagina nelle sue componenti elementari. Il
layout che scegliamo in questo caso è il TableLayout e le componenti elementari sono gli Ext.Panel.
Identificheremo un oggetto generale che conterrà l'intera pagina e lo chiameremo "journal".
var journal = new Ext.Panel({
id:'journal-panel',
title: 'La gazzetta del 2.0',
layout:'table',
width:800,
height:700,
layoutConfig: {
columns: 4
},
frame:true,
items: [new Ext.Panel({
title: 'The best test in all site',
frame:true,
html: '<p>Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text
ever since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.</p><br><p>It has survived not only
five centuries, but also the leap into electronic typesetting, remaining
essentially unchanged.</p>',
rowspan: 2,
colspan: 3
}),new Ext.Panel({
html: '<center><img src="img/1.png"></center>',
frame:true
}),{
html: '<center><img src="img/2.png"></center>',
frame:true
}, ….

Le scatole cinesi
Abbiamo un Panel, che contiene un Panel che ne contiene altri e così via. Gli attributi che possiamo
identificare sono pertanto un set che tende a ripetersi. In questo caso, ad esempio, vediamo:
id: identificatore univoco del layer, va a coincidere con l'id del div associato all'HTML generato da
Ext per renderizzare il nostro Ext.Panel – di default è un identificativo autogenerato dalla libreria -.
title: il testo del titolo che verrà visualizzato nell'intestazione del pannello (una stringa vuota è il
valore di default). Quando un titolo è specificato l'intestazione dell'elemento verrà automaticamente
creata e visualizzata a meno che non si dichiari esplicitamente l'attributo header:false.
layout: la disposizione da utilizzare in questo Container. Se non si specifica un
Ext.layout.ContainerLayout, verrà visualizzata un'impostazione predefinita. I valori validi sono:
absolute, accordion, anchor, border, card, column, fit, form and table.
width: la larghezza di questa componente in pixel (il default è auto).
height: l'altezza di questa componente in pixel (il default è auto).
layoutConfig: si tratta di un oggetto di configurazione contenente le proprietà specifiche per la
scelta del layout. Per maggiori dettagli per quanto riguarda le opzioni di configurazione validi per
ogni tipo di layout, consiglio di visualizzare le API di Ext in merito a:
Ext.layout.Absolute
Ext.layout.Accordion
Ext.layout.AnchorLayout
Ext.layout.BorderLayout
Ext.layout.CardLayout
Ext.layout.ColumnLayout
Ext.layout.FitLayout
Ext.layout.FormLayout
Ext.layout.TableLayout
frame: è impostato a true per renderizzare il pannello con uno stile personalizzato con bordi
arrotondati e integrato nella grafica generale del pannello; false per renderizzare un pannello
generico con il bordo quadrato di 1px (il valore di default è false).
items: un unico elemento o un insieme di componenti figlie che verranno aggiunte al Container
principale. Ogni elemento può essere qualsiasi tipo di oggetto che estende Ext.Component. Gli item
vengono specificati ognuno dentro a parentesi graffe e tutti racchiusi da due parentesi quadre, cosi':
[{…},{…},{…}].
Ogni elemento tra parentesi graffe, nel nostro esempio, è a sua volta un Ext.Panel. Si potrebbero
definire esternamente alla variabile journal i diversi Ext.Panel che conterranno i vari riquadri
della nostra pagina e in seguito inserirli nell'attributo items di journal, separandoli solo da virgole,
senza necessità delle parentesi graffe. In pratica items è un Array di oggetti contenuti
nell'Ext.Panel. A sua volta ogni oggetto figlio conterrà elementi in items oppure un attributo
HTML di seguito descritto.
html: un frammento di HTML, o un DomHelper di Ext (vedremo nei prossimi articoli come si
utilizzano queste utility per creare codice HTML direttamente dal Javascript).
Il risultato del nostro lavoro è visibile qui. Disponibile anche il pacchetto zip con il materiale
completo.

Attenzione a IE
Colgo l'occasione di questo articolo per presentare il primo di tanti errori curiosi che un
programmatore newbie non riuscirebbe a identificare molto semplicemente, data la natura poco
chiara del codice di errore che incontriamo nel visualizzare il nostro oggetto Ext in cui è presente il
seguente baco di programmazione.
Figura 2 - Errore

Questo errore lo troviamo in Internet Explorer. La dicitura "Impossibile completare l'operazione a


causa di un errore 80020101" non è molto esplicativa, né in italiano né in inglese. Credo di
risparmiare qualche ora di lavoro ai futuri programmatori Ext facendo loro notare che si tratta di
una virgola in più nella nostra lista di attributi o di items. Pare che in questo caso IE pretenda una
certa pulizia del codice, infatti, e che, mentre Firefox o Safari o Opera ignorano il fatto che alla fine
della nostra lista si presenti una virgola a cui non seguono elementi, il browser di Microsoft si
blocca e non renderizza per niente la nostra pagina.

Conclusioni e anticipazioni
Abbiamo diviso il nostro articolo in due parti in modo che i lettori possano metabolizzare i concetti
introdotti e il primo esempio di oggetti nidificati uno nell'altro. Nel prossimo articolo esporremo un
esempio di oggetti Window che produrranno un effetto di bacheca di post-it.

Ext.js: il componente Window


Partiamo rapidi sulla base di quanto visto nell'articolo prcedente: principi di programmazione
Object Oriented, catene di ereditarietà che dall'oggetto Observable ci hanno condotto alla classe
Ext.Panel, l'esempio di impaginazione complessa e nidificata di oggetti ottenuto tramite alcuni degli
attributi principali di Panel.
Le Window
Suddividere una pagina in zone risulta quindi semplice. Associare a queste zone dei Panel, è una
facile conseguenza. Se volessimo che questi Panel siano trascinabili (draggable) all'interno della
nostra pagina, basterebbe definire la proprietà draggable : true. Ma chiediamo di più alle
nostre interfacce e cominciamo a pensare che siamo nel Web 2.0, ovvero in un mondo fatto di
contenuti rapidi, personalizzabili, condivisibili, estendibili e estremamente vicini alla user
experience quotidiana che un qualsiasi utente ha con il suo pc. Ecco che la catena evolutiva delle
nostre pagine ci porta quindi alla nascita dell'oggetto Window.
Figura 1 - Gerarchia dell'oggetto Window

Cos'è una Window


Una Window è un pannello specializzato per essere utilizzato come finestra di un'applicazione. Le
Windows sono trascinabili per default e possiedono caratteristiche specifiche come le proprietà di
maximize e restore. Iniziare a lavorare con le Windows è utile in quanto avvicina il programmatore
di interfacce web alle complessità che normalmente sono tipiche di una programmazione più
sofisticata, collegata al mondo desktop.
Proprietà di Window Manager, per capire qual è la finestra visualizzata in un determinato momento,
quali sono le finestre aperte e come sono collegate una all'altra; così come un Focus Manager, per
capire come la finestra che è attiva debba comportarsi e debba vincolare il movimento del mouse;
sono tutte problematiche che riguardano gli sviluppatori di applicazioni desktop oriented.
Cominciare a sentirne parlare e venire a contatto con questi temi, aiuta il programmatore web a
entrare nelle dinamiche di disegno GUI che portano gli appassionati di Web 2.0 a parlare di Web
Application. Allo stesso tempo, grazie ad Ext, non abbiamo necessità di concentrarci
eccessivamente su queste caratteristiche, in quanto la libreria ci soccorre anche in questo frangente
con le sue utilities.
Una Window può quindi essere collegata a un Ext.WindowGroup o gestita dall'
Ext.WindowManager che fornisce le utiliities che abbiamo citato.

Gli Attributi di una Window


Nell'articolo precedente non abbiamo potuto parlare di tutti gli attributi dell'oggetto Panel,
rimandando il lettore a una consultazione delle API di Ext scaricabili dal sito . Essendo Window
un'estensione di Panel, riusciamo ad ereditare nella prima tutte le caratteristiche del secondo.
Pertanto rinnovo l'invito alla consultazione delle API. Prima però di procedere con l'analisi
dell'esempio possiamo vedere insieme alcune delle caratteristiche più interessanti e immediate che
le Window aggiungono al Panel per specializzarlo.
Abbiamo scelto le seguenti proprietà:
closable: true/false. Questa caratteristica istruisce la libreria Ext a renderizzare la window in modo
che si possa chiudere (true) o meno (false). Se è true, viene mostrato il pulsante 'close' sulla barra di
header della finestra, false la nasconde. Chiudere una finestra, per default, significa distruggerla e
quindi non poterla riutilizzare. è possibile comunque personalizzare questo comportamento
associando funzioni all'evento close o comunque permettere a una Window di nascondersi (hide)
Window in modo da poterla mostrare nuovamente a fronte di un evento open/show. Per far questo
basta semplicemente settare l'attributo closeAction su 'hide'.
constrain: true per vincolare la finestra alla porzione di schermo dedicata dal browser alla nostra
pagina (viewport), false per consentirle di uscire al di fuori dei limiti di viewport (il default è false).
defaultButton: l'id di un bottone che deve ricevere il focus del cursore quando la finestra viene
attivata (ovvero riceve il focus a sua volta).
draggable: true, per consentire alla finestra di essere trascinata dalla barra di header, false per
disattivare il trascinamento (il default è true).
manager: un riferimento a un WindowGroup che, come abbiamo detto prima, può implementare
delle policy di gestione della finestra in un contesto con più window da gestire (default
Ext.WindowMgr).
maximizable: true per mostrare il bottone 'maximize' e permettere all'utente di massimizzare la
finestra, false per nascondere il pulsante e impedire che questa venga massimizzata (default false).
minHeight: l'altezza minima in pixel che può raggiungere una finestra (default 100). Questa
proprietà funziona solo quando la proprietà resizable è uguale a true.
minWidth: la larghezza minima in pixel che puo' raggiungere una finestra (default 200). Questa
proprietà funziona solo quando la proprietà resizable è uguale a true.
minimizable: true per mostrare il bottone 'minimize' e permettere all'utente di minimizzare la
finestra, false per nascondere il pulsante e impedire che questa venga minimizzata (default false).
modal: true per far sì che questa finestra si ponga al di sopra delle altre e che non si possa cliccare
su nessun altra prima di chiuderla, in quanto viene steso uno strato (overlay) che copre l'intero
viewport (default a false).
resizable: true per consentire il ridimensionamento da parte dell'utente dal bordo e da ogni angolo
della finestra, false per disattivare il ridimensionamento (il default è true).
x: la posizione X dell'angolo in alto a sinistra della finestra nel momento in cui viene aperta.
y: la posizione Y dell'angolo in alto a sinistra della finestra nel momento in cui viene aperta.

Creiamo un x-theme per i nostri post-it


Veniamo al nostro esempio. Abbiamo immaginato di creare una pagina che fungerà da bacheca di
post-it. Più avanti nei nostri esempi potremo imparare a rendere dinamico un piccolo applicativo del
genere in modo che possa memorizzare i contenuti, la posizione, le dimensioni e lo stato
(mimizzato, nascosto, massimizzato, chiuso) dei vari post-it. Per ora continuiamo il nostro percorso
formativo limitandoci a vedere come strutturare il lato di presentazione (front-end) della nostra web
application.
Figura 2 - Screenshot dell'esempio
Immaginiamo la nostra applicazione con un pulsante in alto a sinistra che diventerà il generatore dei
nostri post-it. Dopo di che costruiamo il nostro x-theme per i post-it, secondo quanto imparato
nell'articolo Temi e Layout. Creiamo una cartella di nome 'postit'. Al suo interno copiamo tutte le
immagini che troviamo nei temi gray o default e che modifichiamo opportunamente perché siano ad
hoc per la nostra web application. Nel nostro caso, ad esempio, vogliamo che le finestre mostrino
una predominanza del colore giallo tipico degli omonimi fogliettini appicicosi che popolano le
nostre scrivanie.
Poi creiamo un file di nome 'xtheme-postit.css' con tutte le caratteristiche tipiche degli x-theme e
cambiamo tutti i path al suo interno in modo che puntino alla nostra cartella 'postit' (collocata dentro
a ext/resources/images come tutti gli altri x-theme). Modifichiamo eventuali caratteristiche di stile,
come il font che ci interessa, la sua dimensione o altro. Infine applichiamo il tema appena generato
alle nostre finestre attraverso il seguente comando, collocato tra le prime righe del nostro file
Javascript:
Ext.util.CSS.swapStyleSheet('theme', '../ext/resources/css/xtheme-postit.css');

Scriviamo il codice del nostro Post-it Generator


Il codice della nostra pagina HTML è molto breve e semplice. Questo perché utilizziamo una
tecnica di programmazione chiamata unobtrusive Javascript. In pratica scriviamo gli elementi base
della struttura della nostra pagina e li rendiamo intelligenti all'interno del codice Javascript
associato. Così facendo applichiamo anche al Javascript quel pattern (metodo) vincente di codifica
che va dietro al nome di MVC (Model-View-Controller); ovvero dividiamo lo strato di disegno
dell'applicazione dalle logiche che implementano il funzionamento delle varie componenti.
Applicando queste tecniche semplificate riusciamo a rendere la nostra applicazione pulita,
facilmente distribuibile, manipolabile ed estendibile senza che si debba mettere mano alla logica di
sviluppo.
Il file, che chiameremo 'window.html' sarà cosi' composto:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>EXAMPLE 3.2 WINDOW...</title>
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css" /
>
<script type="text/javascript" src="../ext/adapter/ext/ext-
base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>
</head>
<body style="font-family:Verdana, Helvetica, Arial;font-
size:10pt;background:#323232">
<input type="button" id="show-btn" value="Post It Generator" /><br /><br />
<script type="text/javascript" src="js/window.js"></script>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>EXAMPLE 3.2 WINDOW...</title>
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css" /
>
<script type="text/javascript" src="../ext/adapter/ext/ext-
base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>
</head>
<body style="font-family:Verdana, Helvetica, Arial;font-
size:10pt;background:#323232">
<input type="button" id="show-btn" value="Post It Generator" /><br /><br />

<script type="text/javascript" src="js/window.js"></script>


</body>
</html>

Disegniamo la nostra pagina con un elemento input di tipo button, con id uguale a show-btn e
valore uguale Post It Generator. Il valore, come ben sappiamo, lo ritroveremo sullo schermo, nella
nostra pagina renderizzata dal browser. Ricordiamoci invece l'id. Lo rivedremo nel codice
Javascript che, come abbiamo detto prima, sarà in grado di rendere intelligente il nostro bottone a
fronte dell'evento click.
Nel file che chiameremo 'window.js' troviamo il seguente semplice codice:
Ext.onReady(function(){
var win;
var button = Ext.get('show-btn');
var bd = Ext.getBody();
Ext.util.CSS.swapStyleSheet('theme', '../ext/resources/css/xtheme-
postit.css');
var cnt=0;
var xPos=100;
var yPos=100;

button.on('click', function(){
// create the window on the first click and reuse on subsequent clicks
cnt++;
xPos+=50;
yPos+=50;
if (xPos>=300)
{
xPos=120;
yPos=100;
}

createPostIt(cnt,xPos,yPos);
});

var createPostIt=function(cnt,xPos,yPos){
var win = new Ext.Window({
title:'Postit #'+cnt,
id:'win'+cnt,
layout:'fit',
width:500,
height:300,
x:xPos,
y:yPos,
closeAction:'hide',
frame:true,
items: new Ext.Panel({
title: 'The best test in all site',
layout:'fit',
frame:true,
Html: '<p>Lorem Ipsum is simply dummy text of the printing and
typesetting industry. '+
'Lorem Ipsum has been the industry\'s standard dummy text ever since
the 1500s, '+
'when an unknown printer took a galley of type and scrambled it to
make a type '+

'(injected humour and the like).</p>',
}),
buttons: [{
text: 'Close',
handler: function(){
win.hide();
}
}]
});
win.show(this);
}
});

Cominciamo indicando al browser di partire a interpretare il nostro codice Javascript solo dopo che
la pagina è stata caricata (Ext.onReady). Dopo di che creiamo qualche variabile di shortcut per gli
elementi che utilizzeremo più spesso nel nostro codice. Si noti come abbiamo messo nella variabile
button l'oggetto input che abbiamo descritto nella nostra pagina HTML tramite l'id che avevamo
notato prima.
Associamo un'azione all'evento di click del pulsante rappresentato dalla variabile button. Qui
troviamo il codice con cui creiamo la nostra finestra, in modo che ad ogni click venga disegnata con
gli attributi rappresentati tra parentesi graffe, all'interno della dicitura new
Ext.Window({…});.
Ci siamo permessi di aggiungere una finezza, memorizzando le posizioni di x e y della finestra
precedente quando esiste, altrimenti le abbiamo inizializzate a 100, fuori dalla funzione handler
dell'evento. In questa maniera riusciamo a produrre un gradevole effetto cascade per ogni finestra
aperta in successione.
Infine aggiungiamo un pulsante alla finestra che permetterà di nascondere la finestra quando viene
premuto.
Il risultato del nostro lavoro è visibile qui. Disponibile anche il pacchetto zip con gli esempi.

Conclusioni e anticipazioni
Con questo esempio terminiamo l'articolo doppio su Panel e Window. Siamo riusciti a vedere come
impostare i due principali oggetti che compongono una web application e abbiamo continuato il
nostro cammino nelle tecniche di disegno di GUI crossbrowser utilizzando Ext.js. Negli articoli che
seguiranno vedremo cosa mettere dentro alle nostre finestre, partiremo analizzando Form e Griglie e
proseguiremo con TabPanel, Accordion e altre utilities che coinvolgeremo nei nostri disegni.

Ext.js: creare form di base


In questo articolo della serie dedicata a Ext.js parleremo dei form, come si realizzano, come si
usano e da cosa sono composti.

Elenco delle componenti di un form


Per iniziare a comprendere i form dobbiamo pensare a tutte le componenti che abbiamo utilizzato
fino ad ora nei nostri moduli online e a come queste sono state tradotte in Ext. Oltre agli elementi
comuni e a cui siamo stati abituati, Ext introduce dei campi innovativi (textarea con testo enriched o
calendari per i campi data, etc) che ci permettono di non dover utilizzare funzioni o elementi esterni
ad Ext per la validazione e di risparmiare quindi parecchio tempo nell’implementazione delle nostre
pagine.
Abbiamo quindi:
Checkbox: checkbox di controllo unico campo. Può essere usato come una sostituzione diretta per
la checkbox tradizionale.
CheckboxGroup: un gruppo che contiene diversi controlli Checkbox.
Combo Box: un controllo ComboBox con il supporto per autocomplete, remoto-loading, di
paginazione e molte altre caratteristiche
DateField: prevede una data di ingresso con un Ext.DatePicker (un calendario) a discesa automatica
e possibilità di validazione complessa della data.
FieldSet: contenitore standard utilizzato per il raggruppamento di più campi di un modulo.
Hidden: per inserire i nostri campi nascosti nel form.
HtmlEditor: una textarea enriched con caratteristiche avanzate per la formattazione del testo, per
la validazione e con possibilità di utilizzo di altri plugin Ext per l’inserimento di immagini e tabelle
complesse.
NumberField: Un campo di testo numerico che fornisce un controllo automatico dei tasti che
possono essere accettati e avanzati controlli di validazione.
Radio: il classico campo radio. Simile al controllo checkbox. Un RadioGroup è gestito
automaticamente dal browser se si assegna a ciascun radio in un gruppo lo stesso nome.
Radio Group: un gruppo che contiene diversi controlli Radio.
TextArea: campo di testo multilinea. Può essere usato come una sostituzione diretta per i
tradizionali campi di testo, in più aggiunge il supporto per auto-sizing.
TextField: campo di testo tradizionale. Può essere usato come una sostituzione diretta dei campi
tradizionali o come classe di base per più sofisticati controlli di input (come Ext.form.TextArea e
Ext.form.ComboBox).
TimeField: prevede un orario da inserire nel campo con una lista di tempi a discesa e controlli di
validazione automatica di orari.

Validazioni e messaggistica
Analizzeremo insieme alcuni degli esempi rilasciati da Ext per la sezione Form e per i suoi controlli
complessi. In tutti questi form vedremo come Ext riesca a farci dimenticare i vecchi controlli
Javascript per validazione di date, numeri, presenza di un campo, lunghezza e quant’altro grazie ai
meccanismi di validazione associati ad ogni form.
Ogni elemento può provvedere a validarsi da sé per via dei controlli onBlur. Se questi sono
attivati, non appena il cursore abbandona (onBlur) il campo in questione si può vedere l’elemento
contrassegnato da un simbolo di errore nel caso in cui il dato inserito non sia corretto. Questa
proprietà viene attivata dal campo booleano (true/false) validateOnBlur.
Un’altra caratteristica fondamentale di ogni elemento è quella di poter comunque esplicitare un
proprio meccanismo di validazione attraverso l’attributo validator, ovvero una funzione
personalizzata di validazione che viene chiamata durante la validazione del campo o del form (il
default è null). Se disponibile, questa funzione sarà chiamata solo dopo che il validatori di base
ritornano true. Deve restituire boolean true se il valore è valido o una stringa di messaggio di errore
in caso contrario.
Immaginiamo ora di avere un oggetto Ext.form che si chiama dataForm. Per scatenare la
validazione del modulo è sufficiente scrivere la seguente riga di codice:
dataForm.getForm().isValid().
Se vogliamo che il form scateni l’evento di submit, basterà scrivere:
dataForm.getForm().getEl().dom.submit().
Come abbiamo detto negli articoli precedenti, ogni oggetto ha una catena di ereditarietà che ne può
spiegare i comportamenti. L’oggetto Ext.Form, in particolare, estende Ext.BasicForm. La
BasicForm è configurata utilizzando l’initialConfig dei FormPanel - che è l'oggetto di
configurazione passato al costruttore. Ciò significa che se si ha un FormPanel e si desidera
configurare il BasicForm, sarà necessario inserire delle opzioni di configurazione per il BasicForm
nelle proprietà di initialConfig.
FormPanel utilizza un Ext.layout.FormLayout implicito nella sua dichiarazione ed è necessario
perché i campi e le etichette funzionino correttamente all'interno del FormPanel.
Per impostazione predefinita, i moduli inviano tramite Ajax, utilizzando una Ext.form.Action. In
questa maniera si possono gestire i messaggi di ritorno dal server a fronte di un inserimento o di un
update e fare con il nostro panel ciò che i paradigmi Ajax ci hanno insegnato a fare negli ultimi
anni.

Esempi pratici
Su questa pagina possiamo recuperare alcuni form che ci aiutano a prendere subito confidenza con
questo oggetto. Analizzeremo ora i form presenti in questo esempio.
Figura 1 - Form 1 - Esempio semplice
Questo esempio ci aiuta a vedere quanto è semplice realizzare un form. Il codice che rappresenta il
form che vediamo in figura è:
var simple = new Ext.FormPanel({
labelWidth: 75,
url:'save-form.php',
frame:true,
title: 'Simple Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',

items: [{
fieldLabel: 'First Name',
name: 'first',
allowBlank:false
},{
fieldLabel: 'Last Name',
name: 'last'
},{
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype:'email'
}, new Ext.form.TimeField({
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
})
],

buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});

simple.render(document.body);

Capiamo subito che il FormPanel si comporta esattamente come i panel che abbiamo visto negli
articoli precedenti. Nell’attributo items, infatti, vediamo succedersi i vari elementi del nostro form
e riusciamo a leggere semplicemente ciò che essi rappresenteranno. Alcune particolarità le vediamo
nell’oggetto Email che utilizza l’attributo vtype (virtual type) che serve a creare una validazione
per gli oggetti email (nella seconda parte di questo articolo vedremo nel dettaglio come si crea una
validazione virtuale). Inoltre vediamo il campo TimeField che descrive perfettamente un elenco
di orari dalle 8 del mattino alle 6 del pomeriggio. Fino a qualche anno fa, un campo del genere, in
autocomplete, non sarebbe stato di così rapida implementazione nemmeno per i più bravi esperti
Javascript.
Grazie all’attributo defaultType: 'textfield', gli elementi elencati in items che non
presentano caratteristiche di xtype (tipologia: date, time, number, etc) sono rappresentati
automaticamente da un textfield.
Figura 2 - Form 2 - Aggiungere fieldset
Raggruppare gli elementi di un form a seconda di ciò che rappresentano è una buona norma che ci
aiuta sia a mantenere puliti i nostri moduli oltre che a renderli più utilizzabili da parte dell’utente.
Un’altra buona norma è non far comparire ciò che è opzionale e renderlo disponibile solo se l’utente
sceglie di vederne il contenuto. Per questi motivi, l’utilizzo dei Fieldset di Ext ci aiuta a disegnare
form complessi che mantengono una pulizia e un’usabilità non indifferenti.
Il codice che rappresenta il form in figura 2 è il seguente:
var fsf = new Ext.FormPanel({
labelWidth: 75,
url:'save-form.php',
frame:true,
title: 'Simple Form with FieldSets',
bodyStyle:'padding:5px 5px 0',
width: 350,

items: [{
xtype:'fieldset',
checkboxToggle:true,
title: 'User Information',
autoHeight:true,
defaults: {width: 210},
defaultType: 'textfield',
collapsed: true,
items :[{
fieldLabel: 'First Name',
name: 'first',
allowBlank:false
},{
fieldLabel: 'Last Name',
name: 'last'
},{
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype:'email'
}
]
},{
xtype:'fieldset',
title: 'Phone Number',
collapsible: true,
autoHeight:true,
defaults: {width: 210},
defaultType: 'textfield',
items :[{
fieldLabel: 'Home',
name: 'home',
value: '(888) 555-1212'
},{
fieldLabel: 'Business',
name: 'business'
},{
fieldLabel: 'Mobile',
name: 'mobile'
},{
fieldLabel: 'Fax',
name: 'fax'
}
]
}],

buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});

fsf.render(document.body);

Possiamo notare come all’interno di items vengano inseriti due fieldset che a loro volta
contengono un attributo items in cui si succedono gli oggetti del form. I fieldset possono essere
rappresentati da checkbox o da elementi che rendono espandibile il fieldset stesso e hanno
caratteristiche che possono far comparire già aperto o meno un gruppo di elementi.
Figura 3 - Form 3 - Un form complesso

Anche se i fieldset e i layout ci aiutano a disporre in maniera ordinate i nostri campi, ciò potrebbe
non bastare ai clienti più esigenti; ecco che quindi vediamo tramite questo esempio come si possano
disporre tramite un TableLayout gli elementi della nostra pagina. In questo esempio inoltre vediamo
il primo esempio di htmleditor. Il codice che rappresenta questo form in particolare è il seguente:
var top = new Ext.FormPanel({
labelAlign: 'top',
frame:true,
title: 'Multi Column, Nested Layouts and Anchoring',
bodyStyle:'padding:5px 5px 0',
width: 600,
items: [{
layout:'column',
items:[{
columnWidth:.5,
layout: 'form',
items: [{
xtype:'textfield',
fieldLabel: 'First Name',
name: 'first',
anchor:'95%'
}, {
xtype:'textfield',
fieldLabel: 'Company',
name: 'company',
anchor:'95%'
}]
},{
columnWidth:.5,
layout: 'form',
items: [{
xtype:'textfield',
fieldLabel: 'Last Name',
name: 'last',
anchor:'95%'
},{
xtype:'textfield',
fieldLabel: 'Email',
name: 'email',
vtype:'email',
anchor:'95%'
}]
}]
},{
xtype:'htmleditor',
id:'bio',
fieldLabel:'Biography',
height:200,
anchor:'98%'
}],

buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});

Figura 4 - Form 4 - Form e TabPanel


I form possono essere disposti anche su più tab. In questo modo le informazioni possono essere
distribuite in maniera ancora più pulita e vincolata dalla presenza o meno di dati nel tab precedente.
Il codice che rappresenta questo form è il seguente:
var tabs = new Ext.FormPanel({
labelWidth: 75,
border:false,
width: 350,

items: {
xtype:'tabpanel',
activeTab: 0,
defaults:{autoHeight:true, bodyStyle:'padding:10px'},
items:[{
title:'Personal Details',
layout:'form',
defaults: {width: 230},
defaultType: 'textfield',

items: [{
fieldLabel: 'First Name',
name: 'first',
allowBlank:false,
value: 'Jack'
},{
fieldLabel: 'Last Name',
name: 'last',
value: 'Slocum'
},{
fieldLabel: 'Company',
name: 'company',
value: 'Ext JS'
}, {
fieldLabel: 'Email',
name: 'email',
vtype:'email'
}]
},{
title:'Phone Numbers',
layout:'form',
defaults: {width: 230},
defaultType: 'textfield',

items: [{
fieldLabel: 'Home',
name: 'home',
value: '(888) 555-1212'
},{
fieldLabel: 'Business',
name: 'business'
},{
fieldLabel: 'Mobile',
name: 'mobile'
},{
fieldLabel: 'Fax',
name: 'fax'
}]
}]
},

buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});

Figura 5 - Form 5 - Form che contengono pannelli a tab

L’ultimo form dell’elenco è un mix di quanto abbiamo visto nei form precedenti. Il codice non ci è
permesso di scriverlo per limiti di spazio ma è possibile recuperare il codice Javascript di tutti e
cinque gli esempi su questa pagina.
In particolare troveremo caratteristiche speciali come:
l’attributo allowBlank:true/false, che determina se un campo è obbligatorio o meno.
allowDecimals, per i campi number. Possiamo descrivere se un numero accetta decimali e
quanti ne accetta.
allowNegative, per i campi number. Possiamo descrivere se un campo accetta numeri negativi.
invalidText: il testo che si può inserire come messaggio quando un campo risulta non valido.
Vedere tutte le caratteristiche in un solo articolo è impossibile. Ma in questo modo abbiamo
cominciato a muovere i nostri primi passi nell’interazione donataci dal form. Quando dobbiamo
utilizzare degli elementi e vogliamo verificarne le caratteristiche, possiamo andare a questo url
(http://extjs.com/deploy/dev/docs/) e troveremo piccoli esempi e descrizioni di ogni attributo che ci
possa sembrare utile ai nostri scopi.
Conclusioni e anticipazioni
Rimangono ancora da trattare alcuni argomenti perché si possa considerare chiusa questa
panoramica sui form. La seconda parte di questo articolo tratterà i seguenti argomenti: Advanced
Validation, checkbox/Radio Groups, multiSelect and ItemSelector, e combobox, Basic Combo
Box, ComboBox Templates.

Ext.js: creare form avanzati


Nella prima parte di questo articolo abbiamo visto come dichiarare dei pannelli Ext di tipo
FormPanel, come creare dei moduli con differenti layout e una carrellata rapida dei campi che si
possono inserire all'interno dei nostri form. In questa parte cercheremo di fare un passo avanti
continuando un'analisi degli esempi proposti sul sito di Ext su questa pagina e affrontando
dettagliatamente le problematiche di interazione di un elemento.

Validazioni dei campi


Innanzitutto possiamo fare qualche considerazione sulla validazione. Tutti i campi che si possono
inserire in un form hanno un attributo validator che serve a definire la funzione di validazione
che si vuole utilizzare al momento del submit (ovvero quando il form riceve un evento che lo porta
a inviare i dati all'indirizzo esplicitato nell'attributo url). Ad esempio:
namePrimary = new Ext.form.TextField({
fieldLabel: 'Name/Group',
name: 'namePrimary',
allowBlank: true,
msgTarget: 'under',
validator:function(value){
return yourConditionTesting(value) || 'valore non valido' ;
}
})

In particolare notiamo come nell'attributo validator abbiamo definito una chiamata a una
funzione a partire dal valore che sta assumendo il nostro campo di testo al momento della
validazione messa in OR ( || ) con un messaggio di errore ('valore non valido'). In questo modo il
validator assume valore uguale al booleano true o al messaggio da riportare sul form per
segnalare l'invalidità del campo.
Un altro modo per testare la validità di un form è dato dall'istruzione form.isValid(). Per
utilizzarlo nei nostri applicativi potremmo scrivere una funzione Javascript con il codice che segue:
var msg, valid = true;
form.items.each(function(field){
msg = field.isValid(true);
if(msg !== true ){ //true to suppress invalidMarking
alert(field.fieldLabel + ' is invalid:' + msg );
valid = false;
}
});
return valid;

Esistono molti attributi che possiamo associare a un elemento Ext per poter gestire al meglio la
validazione. Alcuni campi speciali, come il campo DateField, o il TimeField, o il NumberField e
così via, hanno delle validazioni implicite dettate dal tipo di campo e dai valori che può accettare.
Queste funzionalità faranno sicuramente comodo a chi programma da diversi anni nel campo web: è
infatti molto piacevole potersi sbarazzare di centinaia di righe di funzioni che determinano se un
numero è valido o se una data è scritta correttamente o meno.
Vediamo ora, un rapido elenco di attributi, oltre a validator, che possiamo associare pressappoco a
tutti i campi di un form.
• allowBlank: se settato su false trasforma il campo in obbligatorio (il default è true);
• blankText: è il messaggio di testo da visualizzare se la validazione allowBlank
fallisce (il messaggio di default è "Questo campo è obbligatorio");
• invalidClass: la classe CSS da utilizzare quando si setta un campo non valido (di
default è "x-form-invalid") ;
• invalidText: è il messaggio di testo da visualizzare per settare l'errore nel caso in cui un
campo risulti non valido (il default è "Il valore in questo campo non è valido");
• maxLengthText: è il messaggio di testo da visualizzare se la lunghezza massima viene
superata (il default è "La lunghezza massima di questo campo è x");
• minLengthText: è il messaggio di testo da visualizzare se la lunghezza minima di
convalida non riesce (il default è "La lunghezza minima di questo campo è x");
• regex: un oggetto JavaScript RegExp con cui validare il contenuto di un campo (il default
è nullo). Se disponibile, questa regex sarà valutata solo dopo la che tutti i metodi validatori
ritornano vero. Se il test fallisce, il campo sarà segnato utilizzando regexText;
• regexText: è il messaggio di testo da visualizzare se fallisce il controllo regex (il default
è "");
• validateOnBlur: questo è un attributo molto utile e permette di effettuare delle
validazioni quando il campo perde il focus. Associando una funzione Ajax a questo campo
potremmo ad esempio lanciare un controllo lato server che verifica la presenza di un campo
in un database o cose simili (il default è true);
• validationDelay: il tempo in millisecondi che fa partire la validazione dopo l'input (il
default è 250);
• validationEvent: l'evento che dovrebbe avviare la validazione. Da impostare a false
per disattivare la validazione automatica (il default è "keyup").
Per terminare questo capitolo sulle validazioni semplici, riportiamo ancora due proprietà: format
e nanText. La prima è associata in particolare ai campi DateField e TimeField. In particolare
seguono la formattazione che trovate a questo link. Grazie a questa stringa si possono pilotare le
validazioni sul contenuto dei campi data ed ora. La proprietà nanText, invece, riguarda i campi
numerici ed è il testo del messaggio da visulizzare nel caso in cui il campo non risulti un numero
valido.

Validazione avanzata
Proviamo ora a fare un passo avanti e a vedere come si implementano dei meccanismi di
validazione più sofisticati. Ad esempio possiamo vedere su questa pagina due moduli in cui sono
stati implementati un controllo di validità di password e un controllo di validità su un periodo
temporale. Riportiamo di seguito il codice dei due moduli:
var dr = new Ext.FormPanel({
labelWidth: 125,
frame: true,
title: 'Date Range',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 175},
defaultType: 'datefield',
items: [{
fieldLabel: 'Start Date',
name: 'startdt',
id: 'startdt',
vtype: 'daterange',
endDateField: 'enddt' // id of the end date field
},{
fieldLabel: 'End Date',
name: 'enddt',
id: 'enddt',
vtype: 'daterange',
startDateField: 'startdt' // id of the start date field
}]
});

dr.render('dr');

var pwd = new Ext.FormPanel({


labelWidth: 125,
frame: true,
title: 'Password Verification',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {
width: 175,
inputType: 'password'
},
defaultType: 'textfield',
items: [{
fieldLabel: 'Password',
name: 'pass',
id: 'pass'
},{
fieldLabel: 'Confirm Password',
name: 'pass-cfrm',
vtype: 'password',
initialPassField: 'pass' // id of the initial password field
}]
});

pwd.render('pw');

Dal codice possiamo estrapolare le ultime due proprietà utili alla validazione:
• vtype: utile a richiamare un virtual type da associare al nostro campo;
• vtypeText: utile a mostrare il messaggio di errore a fronte della validazione sul virtual
type.
Implementare un virtual type è molto semplice. Nel codice che segue possiamo vedere come sono
stati implementati i controlli che settano la data minima ( end.setMinValue(date) ) e
massima ( start.setMaxValue(date) ) nei due calendari Ext; e come di seguito sia stato
implementato il vtype password che controlla che le due password digitate siano uguali (var
pwd = Ext.getCmp(field.initialPassField); return (val ==
pwd.getValue()); ).
Ext.apply(Ext.form.VTypes, {
daterange : function(val, field) {
var date = field.parseDate(val);

if(!date){
return;
}
if (field.startDateField && (!this.dateRangeMax || (date.getTime() !=
this.dateRangeMax.getTime()))) {
var start = Ext.getCmp(field.startDateField);
start.setMaxValue(date);
start.validate();
this.dateRangeMax = date;
}
else if (field.endDateField && (!this.dateRangeMin || (date.getTime() !=
this.dateRangeMin.getTime()))) {
var end = Ext.getCmp(field.endDateField);
end.setMinValue(date);
end.validate();
this.dateRangeMin = date;
}

return true;
},

password : function(val, field) {


if (field.initialPassField) {
var pwd = Ext.getCmp(field.initialPassField);
return (val == pwd.getValue());
}
return true;
},

passwordText : 'Passwords do not match'


});

Checkbox/Radio Groups
La nuova versione di Ext ha aggiunto alcune utility per la gestione dei pulsanti checkbox e radio.
Queste utility sono visualizzabili su questa pagina. L'esempio mostra gruppi di pulsanti radio e
checkbox raggruppati tra di loro in molti modi. Per definire un gruppo di pulsanti a scelta multipla
(checkbox) basta elencarli nel consueto attributo/array items e collegarli con un xtype di tipo
checkboxgroup:
{
// Use the default, automatic layout to distribute the controls
evenly
// across a single row
xtype: 'checkboxgroup',
fieldLabel: 'Auto Layout',
items: [
{boxLabel: 'Item 1', name: 'cb-auto-1'},
{boxLabel: 'Item 2', name: 'cb-auto-2', checked: true},
{boxLabel: 'Item 3', name: 'cb-auto-3'},
{boxLabel: 'Item 4', name: 'cb-auto-4'},
{boxLabel: 'Item 5', name: 'cb-auto-5'}
]
}

Per creare un radiogroup si procede in maniera analoga al codice precedente, sostituendo


semplicemente l'xtype.
Le combobox
Per esaminare in maniera completa le potenzialità delle combobox in Ext non basterebbe lo spazio
di due articoli. Grazie alle potenzialità di questo framework, infatti, le combobox diventano un utile
strumento di lavoro all'interno dei nostri moduli. Possiamo infatti costruire elenchi a partire da una
lista di dati interna alla nostra pagina, o da un array Javascript, o da una chiamata Ajax.
Quest'ultima può essere implementata in modo che la richiesta che parte verso il server crei un
effetto in stile autocomplete: lato server viene effettuata una ricerca a seconda di quello che stiamo
digitando e la nostra combobox mostra una tendina con i valori di ritorno della ricerca che
divengono più specifici mano a mano che la parola ricercata va a completarsi.

Basic Combo Box


Possiamo vedere qualche esempio di combobox molto semplice a questo link. La più facile e
immediata in assoluto è la seguente:
// simple array store
var store = new Ext.data.SimpleStore({
fields: ['abbr', 'state', 'nick'],
data : Ext.exampledata.states // from states.js
});
var combo = new Ext.form.ComboBox({
store: store,
displayField:'state',
typeAhead: true,
mode: 'local',
forceSelection: true,
triggerAction: 'all',
emptyText:'Select a state...',
selectOnFocus:true,
applyTo: 'local-states'
});

Nella struttura dati chiamata store, ottenuta tramite la creazione di un'istanza di SimpleStore,
vengono introdotti tre campi; questi tre campi vengono poi valorizzati da una lista di dati ottenuta
dal file states.js. A questo punto la struttura store viene utilizzata come elemento di store (appunto)
della nostra combobox, a cui vengono associate alcune caratteristiche interessanti. Ad esempio una
caratteristica molto utile è l'emptyText, ovvero il testo che viene inserito nella nostra combobox fino
a quando non si va e si comincia a scrivere il valore che stiamo cercando. Un'altra caratteristica che
possiamo notare è che la Ext.form.ComboBox viene associata nella nostra pagina HTML a un
elemento di tipo input type text. Nei prossimi articoli vedremo come si usano le griglie di Ext e
comprederemo piu' cose riguardo agli store di dati, in tale sede riprenderemo in considerazione le
combobox e alcune loro caratteristiche:
<input type="text" id="local-states" size="20"/>

Altre caratteristiche sono molto semplici e intuitive. Si possono comunque trovare elencate su
questa pagina.

ComboBox Templates
Un aspetto associato alle combobox che deve essere tenuto in considerazione è la capacità di queste
ultime di essere associate ad un template HTML. L'uso dei template è riccorrente in Ext. Per chi ha
lavorato con strumenti come Velocity di Apache o altri strumenti Java, la sintasssi dei template può
risultare piuttosto intuitiva. Anche chi non ha conoscenze di disegno di template può comprenderli
semplicemente. Basta capire che le parti variabili in un template sono racchiuse tra parentesi graffe
e che ciò che è contenuto nelle parentesi è un comando o una variabile. Possiamo vedere, per
esempio, il codice su questa pagina.
Vediamo infatti come qualsiasi campo possa risultare una combobox e come a un campo di testo si
possa associare un template complesseo per esporre i risultati di una ricerca Ajax. In particolare il
template utilizzato nell'esempio esposto nel link è il seguente:
// Custom rendering Template
var resultTpl = new Ext.XTemplate(
'<tpl for="."><div class="search-item">',
'<h3><span>{lastPost:date("M j, Y")}<br />by
{author}</span>{title}</h3>',
'{excerpt}',
'</div></tpl>'
);

Il risultato di questo template è un insieme di rige che hanno una formattazione del campo data
(lastPost), e a capo il nome dell'autore e il titolo del post associato.

MultiSelect and ItemSelector


Per concludere la nostra rapida carrellata delle funzioni Ext, possiamo vedere le liste di dati e come
vengono gestite. Nella versione attuale di Ext troviamo questi due componenti grazie al contribuito
a Ext del membro della community TJ Stuart.
Il multiselect è un elenco che consente di selezionare più elementi di una lista, e l'ItemSelector
combina due MultiSelects in un più sofisticato controllo che include drag&drop. Bisogna precisare
che per il momento questi controlli sono ancora implementati come estensioni e che la multiselect
sarà probabilmente migrata in una componente fondamentale in un futuro rilascio. Per vedere due
esempi concreti che utilizzano questa componente basta andare a questo indirizzo.

Conclusione
In questi due articoli abbiamo avuto modo di visionare rapidamente i maggiori componenti di un
modulo. Abbiamo ritenuto utile soffermarci di più su alcuni aspetti come la validazione che
possono essere personalizzati a seconda delle nostre esigenze. Le altre componenti che abbiamo
visto sono molto simili tra loro e una volta comprese le caratteristiche comuni (dato che sono tutte
un'estensione di field) ogni utente potrà utilizzarle in maniera rapida nei propri moduli. La
componente che più potrà essere customizzata e resa unica a seconda del progetto o del sito che
stiamo sviluppando rimane la combobox, che potrà mostrarci liste, tabelle e dati che possono essere
formattati in maniera rapida, velocizzando il disegno delle nostre GUI e l'interazione tra utente e
parte server dei nostri applicativi.

Ext.js: l'oggetto Grid - Opzioni di base


Anche le griglie meritano di essere trattate nel dettaglio come gli ultimi elementi dei nostri articoli
su Ext.js. Prima dell'avvento dei framework Javascript collocare elementi in una griglia significava
creare elementi table nel nostro codice.
Personalizzare le dimensioni, le posizioni, la presenza o l'assenza di una colonna, o l'ordinamento
dei dati in tabella, significava dover ridisegnare la pagina e assegnare attributi width ed height
a ogni colonna, oltre ad altri pesanti accorgimenti.
Se si voleva creare griglie più elaborate, si doveva ricorrere ad applet Java o ActiveX Windows che
abilitassero la possibilità di visualizzare elementi più dinamici ma più pesanti, poco flessibili e poco
portabili. Le griglie di Ext, visibili su questa pagina, sono quanto di più dinamico si possa
immaginare in ambito DHTML. Le colonne sono ridimensionabili, mobili, possono essere fatte
scomparire e apparire facilmente e, se usiamo le variabili di stato in maniera opportuna, un utente
può anche facilmente memorizzare le caratteristiche che preferisce tramite cookie o altre strategie
che si appoggiano su database o simili.

Differenti tipologie di griglia


Ext ci aiuta a poter creare molte tipologie di griglie differenti. Possiamo caratterizzare le nostre
griglie, infatti, con attributi che rendono editabili le celle della griglia, oppure possiamo creare delle
griglie con elementi raggruppabili (come in un client di posta, per esempio), o ancora è possibile
creare griglie con una colonna di checkbox iniziale, utile a selezionare più elementi
contemporaneamente.
Si possono caricare i dati tramite una struttura Javascript semplice interna alla nostra pagina js.
Oppure è possibile lanciare chiamate Ajax che caricano le nostre griglie dinamicamente, in modo da
poter gestire anche la paginazione dei dati; è possibile caricare i dati da un file XML e mappare in
maniera intuitiva la struttura del file XML con una griglia che espone i contenuti in maniera master-
detail, ovvero: a fronte della selezione di una riga, verrà mostrato un pannello con dati organizzati
in un template utile a dettagliare le poche informazioni presenti nella griglia. Proprio un esempio
come questo sarà trattato più nel dettaglio nel corso di questo articolo.

Lo store
Il primo elemento utile a descrivere una grigliaè il suo contenuto. Come riempirla e come
formattare gli elementi che verranno mostrati in tabella, è compito dello store.
La classe Store incapsula una cache client side di record di oggetti che forniscono dati di input per i
componenti, come il GridPanel, la ComboBox, o il DataView. Un oggetto Store utilizza un oggetto
che viene chiamato DataProxy per accedere ai dati. Questa classe è una base astratta per
implementazioni che prevedono il recupero di dati non formattati. Le implementazioni di
DataProxy sono utilizzate in combinazione con un oggetto Ext.data.DataReader (costruito ad hoc a
seconda dell'oggetto che devono andara a leggere -ad esempio possono interpretare oggetti JSON o
XML). Quello che viene poi creato da un DataProxy è un blocco di Ext.data.Records che tornano
finalmente al nostro Ext.data.Store. Un oggetto Store non è a conoscenza del formato dei dati
restituiti dal proxy.

Il column model
Il secondo oggetto fondamentale nella costruzione di una griglia è il ColumnModel. Questa classe
viene inizializzata con un array di oggetti colonna utili alla configurazione dell'intera griglia.
Una particolare configurazione definisce la stringa di intestazione della colonna stessa, il campo
Ext.data.Record di dati da associare e una funzione opzionale di rendering personalizzata per
aggiustare date o per colorare il testo o lo sfondo a seconda di ciò che è presente nel dato, oppure
ancora per associare immagini a una cella a seconda di cosa contiene.
La capacità di applicare una classe CSS a tutte le celle di una colonna attraverso il suo id è un'altra
delle opzioni di configurazione con cui possiamo formattare il contenuto della nostra griglia in
maniera indipendente dai dati. In questo modo applicheremo a pieno il valido pattern MVC (model,
view, controller) utile a distinguere per bene dati, visualizzazione e informazioni di business, tra
loro.
var colModel = new Ext.grid.ColumnModel([
{header: "Settore", width: 60, sortable: true},
{header: "Azienda", width: 150, sortable: true},
{header: "Fatturato.", width: 100, sortable: true},
{header: "Previsioni", width: 100, sortable: true, renderer:
visualizzaCosti},
{header: "Impiegati", width: 100, sortable: true, resizable: false}
]);

Le opzioni di configurazione definite in questa classe possono comparire in ogni singola colonna,
altrimenti viene affidato loro il valore dio default. Ad esempio, sortable o hideable sono due
attributi che determinano se la colonna può lanciare un evento di ordinamento dei dati o se può
essere nascosta o meno; di default sono due attributi con valore true.

Un esempio pratico
Per cominciare ad andare più a fondo nella descrizione delle griglie, vedremo un esempio
relativamente semplice che ci aiuta a mostrare il contenuto di un file .xml strutturato come segue in
una tabella master-detail:
<?xml version="1.0" encoding="UTF-8"?>
<Articles>

<Article>
<PageUrl>
http://www.ictv.it/file/vedi/728/creare-un-home-page-a-tab-con-ext/
</PageUrl>
<UrlSnippet>
http://www.ictv.it/code_download/728_code.zip
</UrlSnippet>
<ArticleAttributes>
<Author>Nunzio Fiore</Author>
<Type>CODE-IT</Type>
<Title>Creare una homepage a tab con Ext</Title>
<Site>icTV</Site>
<Category>VIDEO</Category>
<HasSnippet>SI</HasSnippet>
<Lang>ITA</Lang>
<Description>Come creare un semplice layout Ext e
predisporre delle schede a tab per il nostro sito in pochi minuti.</Description>
</ArticleAttributes>
</Article>

...
</Articles>

Per poter utilizzare codice Ext nelle nostre pagine, basta includere le tre librerie principali che
definiscono oggetti e strutture CSS:
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-
all.css" />
<script type="text/javascript" src="../ext/adapter/ext/ext-
base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>

A questo punto ci affidiamo completamente alle capacità di Ext di aiutarci a generare codice non-
obtrusive e definiamo esclusivamente un div con un id specifico (ad es. binding-example) che
ci sarà utile nel codice Javascript per poter mappare il nostro oggetto dinamico con un layer che
abbiamo collocato, tramite CSS, nella nostra pagina, indipendentemente dal contenuto complesso
che andremo ad includervi:

<div id="binding-example"></div>

Nel file Javascript attraverseremo nel dettaglio tutte le fasi che abbiamo elencato utili alla creazione
della nostra prima griglia. Abbiamo scelto di costruire un esempio molto pulito e semplice in modo
da poter analizzare istruzione dopo istruzione ciò che avviene durante la creaszione di un oggetto
Ext.GridPanel. Coglieremo l'occasione per rinfrescare anche alcuni concetti che abbiamo visto nelle
scorse occasioni, e vedremo in questo modo le caratteristiche salienti di una griglia.
Cominciamo quindi ad istruire il nostro browser perché inizi a renderizzare le componenti Ext nel
momento in cui la pagina è stata caricata e l'oggetto Ext, creato grazie all'inclusione di ext-all.js e
ext-base.js, ci conferma di essere pronto:
Ext.onReady(function(){

Successivamente inseriamo una componente opzionale, ma molto utile per vedere un oggetto che
studieremo più avanti: Ext.state.Manager. Questo oggetto è utile a memorizzare delle caratteristiche
utili a descrivere gli oggetti Ext; in questo caso avremo una descrizione completa del columnModel,
la presenza, la dimenzione, la posizione delle colonne e molto altro ancora. Nella versione più
semplice e base di Ext, abbiamo l'Ext.state.CookieProvider. Questo oggetto ci permette di
inizializzare un cookie pe rogni oggetto memorizzato contentente informazioni che possono essere
decoficicate in Ext in un oggetto JSON. Nel nostro caso abbiamo istruito il CookieProvider perche'
scada dopo 10 anni:
var cp = new Ext.state.CookieProvider({
path: "/",
expires: new Date(new Date().getTime()+(1000*60*60*24*3650))
})
Ext.state.Manager.setProvider(cp);

Vediamo ora un'istruzione che abbiamo esaminato nell'articolo riguardante i temi e i layout. Con
Ext.util.CSS riusciamo a dire al browser di associare un tema particolare a ogni oggetto mostrato
nella nostra pagina. Il tema in questione è descritto completamente nel file che troviamo a questo
path ../ext/resources/css/xtheme-gray.css:
Ext.util.CSS.swapStyleSheet('theme', '../ext/resources/css/xtheme-
gray.css');

Dopo aver inizializzato quindi il nostro ambiente possiamo passare a descrivere subito l'oggetto che
sta alla base di una griglia, ovvero lo store.
Per inizializzarlo basta creare un'istanza di Ext.data.Store tramite la keyword new.
Uno dei primi attributi che andiamo a definire è url; qui facciamo puntare al file article.xml di cui
parlavamo prima. Subito dopo istruiamo l'oggetto a capire che dovrà leggere il contenuto di ciò che
trova in url come un file Xml. Pertanto associamo all'attributo reader un'istanza di
Ext.data.XmlReader. Nella descrizione degli attributi di XmlReader troviamo una completa
mappatura dei tag xml, in modo che lo store riesca a parserizzare il file xml e i suoi contenuti e
associ un oggetto Ext.data.Record ad ogni elemento del file xml:

// create the Data Store


var store = new Ext.data.Store({
// load using HTTP
url: 'data/articles.xml',

// the return will be XML, so lets set up a reader


reader: new Ext.data.XmlReader({
// records will have an "Article" tag
record: 'Article',
id: 'ASIN',
totalRecords: '@total'
}, [
// set up the fields mapping into the xml doc
// The first needs mapping, the others are very basic
{name: 'Author', mapping: 'ArticleAttributes > Author'},
'Title',
'Site',
'Type',
'Category',
'HasSnippet',
// Detail URL is not part of the column model of the grid
'Lang',
'PageUrl',
'UrlSnippet',
'Description'
])
});

Una volta descritto uno store, si può cominciare a descrivere un GridPanel:


// create the grid
var grid = new Ext.grid.GridPanel({

A cui viene associato lo store creato precedentemente. Notiamo come la parola store compaia sia
dalla parte del nome dell'attributo che dalla parte in cui rappresenta il nome della variabile che
contiene lo store:
store: store,

Arriviamo finalmente a descrivere la seconda componente più importante delle griglie: il


ColumnModel. All'interno dell'array che elenca le colonne che troveremo in tabella, vediamo alcuni
attributi importanti: header, width, dataIndex, sortable. Ce ne sono molti altri e sono
disponibili a questo indirizzo. Quelli che vediamo qui sono tra i più utili e semplici per iniziare. In
header viene descritta la stringa che troveremo nell'intestazione di ogni colonna della nostra
griglia; in width vediamo la dimensione di default che chiediamo di assegnare alla colonna nel
caso in cui non sia stata memorizzata una dimensione dall'utente tramite drag&drop e resize. Se
l'utente fa una modifica alla tabella, per come la stiamo creando, questa modifica viene registrata su
cookie; pertanto se l'utente torna sulla tabella vede la propria dimensione piuttosto che quella di
default. DataIndexè una caratteristica che mappa la colonna con il nome che abbiamo associato a
ogni elemento del Record che abbiamo descritto in precedenza. Sortable, l'abbiamo descritto in
precedenza, attiva o stoppa l'orindamento dei dati:
columns: [
{header: "Title", width: 220, dataIndex: 'Title', sortable:
true},
{header: "Site", width: 100,dataIndex: 'Site', sortable:
true},
{header: "Type", width: 50, dataIndex: 'Type', sortable: true},
{header: "Category", width: 50, dataIndex: 'Category',
sortable: true},
{header: "Lang", width: 50,dataIndex: 'Lang', sortable: true},
{header: "Snip", width: 50, dataIndex: 'HasSnippet', sortable:
true},
{header: "Author", width: 60, dataIndex: 'Author', sortable:
true}
],

Ci sono diverse caratteristiche di selezione che possono essere associate a un grid. Nel nostro
esempio abbiamo deciso di creare una tabella che permetta una selezione alla volta per ogni riga
della griglia. Infine abbiamo inserito le ultime caratteristiche utili a persponalizzare il nostro
esempio. Con forceFit uguale a true, istruiamo la tabella a occupare tutto lo spazio che le viene
messo a disposizione; gli altri attributi sono simili a quelli che abbiamo descritto quando abbiamo
parlato delle componenti panel e window:
sm: new Ext.grid.RowSelectionModel({singleSelect: true}),
viewConfig: {
forceFit: true
},
height:310,
split: true,
region: 'north'
});

La peculiarità del nostro esempio è data dal Template. Dato che stiamo costruendo una tabella
Master/Detail, abbiamo bisogno di un oggetto che descriva come distribuire all'interno del pannello
di dettaglio le informazioni contenute nel file xml e che non necessariamente compaiono in griglia.
La sintassi un template è molto semplice. Vengono utilizzate le parentesi graffe per racchiudere le
parti variabili del codice HTML che inseriamo nell'array del template, successivamente l'array viene
associato come argomento dell'istanza di Ext.Template:
// define a template to use for the detail view
var articleTplMarkup = [
'<b>Title</b>: <a href="{PageUrl}"
target="_blank">{Title}</a><br/>',
'<b>Author</b>: {Author}<br/>',
'<b>Lang</b>: {Lang}<br/>',
'<b>Type</b>: {Type}<br/>',
'<b>Site</b>: {Site}, {Category}<br/>',
'<b>Description</b>: {Description}<br/>',
'<b>Has a snippet for download</b>: {HasSnippet}<br/> ',
'<a href="{UrlSnippet}" target="_blank">{UrlSnippet}</a>',
];

var articleTpl = new Ext.Template(articleTplMarkup);

Finalmente arriviamo a creare il Panel che verrà collegato tramite l'attributo renderTo con il div
con id binding-example che abbiamo visto in precedenza:
var ct = new Ext.Panel({
renderTo: 'binding-example',
frame: true,
title: 'Article List',
width:800,
height: 600,
layout: 'border',

Il pannello che abbiamo creato ha un layout di tipo border. La griglia che abbiamo descritto in
precedenza aveva un attributo region uguale a north, pertanto, associandolo al Panel ct, tramite
l'attributo items, riusciamo a posizionare in alto la griglia e in centro un pannello con id uguale a
detailPanel in cui andremo a sovrascrivere il nostro template a fronte di ogni selezione:
items: [
grid,
{
id: 'detailPanel',
region: 'center',
bodyStyle: {
background: '#fefefe',
padding: '7px'
},
html: '
Please select an article to see additional details.'
}
]
})

Per creare l'effetto di master/detail dobbiamo quindi recuperare l'evento rowselect associato al
selection model della nostra griglia e creare una funzione che sovrascriva il template articleTpl nel
corpo del pannello detailPanel, con i dati contenuti nel record r.data:
grid.getSelectionModel().on('rowselect', function(sm, rowIdx, r) {
var detailPanel = Ext.getCmp('detailPanel');
articleTpl.overwrite(detailPanel.body, r.data);
});

Ultima importante istruzione del nostro esempio è store.load(). Scateniamo così una lettura
dell'url descritto in store, i dati associati al record, il record associato al template e così via:
store.load();

L'esempio che abbiamo visto è disponibile per download.

Conclusione
In questo articolo abbiamo analizzato nel dettaglio le caratteristiche basilari di una griglia, nel
prossimo potremo affrontare argomenti leggermente piu' complessi come il paging, le griglie
editabili, il JsonReader, il GroupingView e il CheckboxSelectionModel.

Ext.js: l'oggetto Grid - Opzioni avanzate


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.