Top Banner
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
43

Guida EXTJS

Jun 11, 2015

Download

Documents

nerosoft

Fonte html.it
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Guida EXTJS

Introduzione a Ext.jsExt.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 licenzaLa 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

Page 2: Guida EXTJS

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 fattiOrmai 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>

Page 3: Guida EXTJS

</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

Page 4: Guida EXTJS

che il contenuto della tab riempia tutta l'area a disposizione. Il risultato è il seguente.

Figura 1 - Screenshot dell'esempio

ConcludendoAbbiamo 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 layoutDopo 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 applicaNelle interfacce Ext, prende il nome di Xtheme l'aggregazione di stylesheet e immagini utili a

Page 5: Guida EXTJS

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 XthemeL'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-selectorRinominiamo 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 temiOra 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)', ''],

Page 6: Guida EXTJS

['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 temiPersonalizzando 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 layoutRisolto 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'}) ] });

Page 7: Guida EXTJS

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 tabCopiamo 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',

Page 8: Guida EXTJS

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 anticipazioniCon 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 PanelAbbiamo 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

Page 9: Guida EXTJS

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 ExtTornando 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 Classbox Ext.BoxComponentbutton Ext.Buttoncolorpalette Ext.ColorPalettecomponent Ext.Componentcontainer Ext.Containercycle Ext.CycleButtondataview Ext.DataViewdatepicker Ext.DatePickereditor Ext.Editoreditorgrid Ext.grid.EditorGridPanelgrid Ext.grid.GridPanelpaging Ext.PagingToolbarpanel Ext.Panelprogress Ext.ProgressBarpropertygrid Ext.grid.PropertyGridslider Ext.Slidersplitbutton Ext.SplitButtonstatusbar Ext.StatusBartabpanel Ext.TabPaneltreepanel Ext.tree.TreePanelviewport Ext.Viewportwindow Ext.Window

Toolbar componentstoolbar Ext.Toolbar

Page 10: Guida EXTJS

tbbutton Ext.Toolbar.Buttontbfill Ext.Toolbar.Filltbitem Ext.Toolbar.Itemtbseparator Ext.Toolbar.Separatortbspacer Ext.Toolbar.Spacertbsplit Ext.Toolbar.SplitButtontbtext Ext.Toolbar.TextItem

Form componentsform Ext.FormPanelcheckbox Ext.form.Checkboxcombo Ext.form.ComboBoxdatefield Ext.form.DateFieldfield Ext.form.Fieldfieldset Ext.form.FieldSethidden Ext.form.Hiddenhtmleditor Ext.form.HtmlEditorlabel Ext.form.Labelnumberfield Ext.form.NumberFieldradio Ext.form.Radiotextarea Ext.form.TextAreatextfield Ext.form.TextFieldtimefield Ext.form.TimeFieldTrigger 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 PanelLa 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.

Page 11: Guida EXTJS

Gli attributi di un PanelGli 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,

Page 12: Guida EXTJS

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 cinesiAbbiamo 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

Page 13: Guida EXTJS

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 IEColgo 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 anticipazioniAbbiamo 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 WindowPartiamo 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.

Page 14: Guida EXTJS

Le WindowSuddividere 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 WindowUna 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 WindowNell'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)

Page 15: Guida EXTJS

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-itVeniamo 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

Page 16: Guida EXTJS

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 GeneratorIl 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-

Page 17: Guida EXTJS

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({

Page 18: Guida EXTJS

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 anticipazioniCon 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

Page 19: Guida EXTJS

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 baseIn 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 formPer 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 messaggisticaAnalizzeremo insieme alcuni degli esempi rilasciati da Ext per la sezione Form e per i suoi controlli

Page 20: Guida EXTJS

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 praticiSu 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

Page 21: Guida EXTJS

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

Page 22: Guida EXTJS

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,

Page 23: Guida EXTJS

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

Page 24: Guida EXTJS

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

Page 25: Guida EXTJS

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',

Page 26: Guida EXTJS

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.

Page 27: Guida EXTJS

Conclusioni e anticipazioniRimangono 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 avanzatiNella 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 campiInnanzitutto 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 invalidMarkingalert(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

Page 28: Guida EXTJS

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 avanzataProviamo 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',

Page 29: Guida EXTJS

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; }

Page 30: Guida EXTJS

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 GroupsLa 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.

Page 31: Guida EXTJS

Le comboboxPer 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 BoxPossiamo 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 TemplatesUn 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ò

Page 32: Guida EXTJS

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 ItemSelectorPer 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.

ConclusioneIn 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 baseAnche 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.

Page 33: Guida EXTJS

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 grigliaExt 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 storeIl 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 modelIl 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.

Page 34: Guida EXTJS

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 praticoPer 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-

Page 35: Guida EXTJS

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

Page 36: Guida EXTJS

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},

Page 37: Guida EXTJS

{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

Page 38: Guida EXTJS

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.

ConclusioneIn 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 avanzateDopo 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

Page 39: Guida EXTJS

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 DataReaderL'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

Page 40: Guida EXTJS

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.

Page 41: Guida EXTJS

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'} ]) });

Page 42: Guida EXTJS

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 praticoAbbiamo 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'} ] });

Page 43: Guida EXTJS

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.

ConclusioneIl 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.