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

Ext JS: progettare interfacce con Ext.Component

Usare Ext.Component per creare elementi di interfaccia, dai più semplici ai più complessi
Usare Ext.Component per creare elementi di interfaccia, dai più semplici ai più complessi
Link copiato negli appunti

Dopo aver introdotto con i primi 5 articoli di questa serie il framework ExtJS da un punto di vista teorico, da questo articolo inizieremo con l'utilizzo vero e proprio della libreria creando interfacce web complesse.

La superclasse Ext.Component

Qualsiasi componente grafico o widget presente in pagina, dal più banale come un bottone al più complesso come una griglia di dati o un grafico, estende in maniera più o meno diretta la classe Ext.Component. Questa classe è astratta e non dovrebbe mai essere istanziata direttamente: tutti i widget necessari all'applicazione estendono e dovranno estendere Ext.Component (o una sua ulteriore sottoclasse).

Tutte le sottoclassi che estendono Ext.Component partecipano al ciclo di vita automatizzato presente in ExtJS che prevede la creazione, il rendering e la distruzione.

L'importanza dell'id e della classe Ext.ComponentMgr

Ogni istanza di Ext.Component creata in pagina ha un id univoco che lo identifica in maniera diretta all'interno dell'applicazione. L'id può essere assegnato in maniera statica dall'utente o può essere gestito dinamicamente dal framework. Questo id ha il duplice scopo di identificare l'elemento HTML che rappresenta il componente e di permettere l'utilizzo della classe Ext.ComponentMgr.

Quest'ultima è una classe statica che si offre come archivio di tutti i componenti presenti in pagina. Grazie al metodo get() è possibile recuperare qualsiasi componente partendo dal suo id. Spesso i componenti, una volta renderizzati in pagina, generano una serie di elementi HTML gerarchicamente collegati. L'id in questo caso fa riferimento solo al tag (spesso un div) più esterno e che rappresenta il componente nel suo insieme.

Ecco un breve esempio nel quale vengono creati tre pannelli, vengono renderizzati all'interno del body della pagina e successivamente vengono modificati a partire dal loro id. Per i primi due pannelli utilizziamo un id personalizzato mentre per il terzo sfruttiamo il motore di generazione di ExtJS (per tutti gli esempi di questo articolo è stata usata la versione 3.2.1 del framework).

<html>
	<head>
		<script src="../extjs/adapter/ext/ext-base.js"></script>
		<script src="../extjs/ext-all.js"></script>
		<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
		<script>
			Ext.onReady(function() {
				new Ext.Panel({
					html: "contenuto del panel 1",
					title: "Pannello 1",
					height: 300,
					width: 400,
					id:"panel1",
					renderTo: Ext.getBody()
				});
				new Ext.Panel({
					html: "contenuto del panel 2",
					title: "Pannello 2",
					height: 300,
					width: 300,
					id:"panel2",
					renderTo: Ext.getBody()
				});
				new Ext.Panel({
					html: "contenuto del panel 3",
					title: "Pannello 3",
					height: 200,
					width: 100,
					renderTo: Ext.getBody()
				});
				Ext.ComponentMgr.get("panel1").setSize(100,200); //cambio dimensioni
				Ext.ComponentMgr.get("panel2").setDisabled(true); //disabilito
				Ext.ComponentMgr.get("ext-comp-1001").destroy(); //distruggo
			});
		</script>
	</head>
	<body>
	</body>
</html>

Analizziamo ora grazie a Firebug il markup generato:

Figura 1 - Analisi del markup con Firebug (click per ingrandire)
screenshot

Ritroviamo un div con id panel1 e un div con id panel2 che rappresentano il componente (che a sua volta è composto da sotto elementi). Ovviamente il div ext-comp-1001 non è presente nel markup perché eliminato.

Da un punto di vista architetturale questo approccio potrà risultare un po' confusionario perché non facilita l'incapsulamento e considera i componenti tutti allo stesso livello globale; molto meglio organizzare il codice in classi sfruttando l'object orientation e modificando la visibilità dei componenti.

L'istanziazione lazy dei componenti: xtype

Il ciclo di vita di una sotto classe di Ext.Component è composto da 3 momenti fondamentali: l'istanziazione, il rendering e la distruzione. Con istanziazione intendiamo il momento in cui viene creato l'oggetto (spesso tramite il costrutto new) e ad esso viene dedicata una porzione di memoria; con rendering intendiamo il momento in cui il componente viene “tradotto” in elementi HTML per essere mostrato in pagina; con distruzione intendiamo il momento in cui la memoria viene liberata e gli elementi in pagina vengono rimossi completamente dal DOM.

Istanziare un componente in maniera lazy significa posticipare la sua creazione sino al momento della sua rendition con un relativi risparmio in termini di risorse occupate. Immaginiamo un'applicazione di una certa entità composta da diversi pannelli, tabelle e finestre organizzati nella classica struttura gerarchica classica di un interfaccia web.

Senza nessuna componente lazy siamo obbligati ad instanziare i diversi componenti all'avvio dell'applicazione per poi mostrarli a tempo debito all'utente.

All'interno di ExtJS è presente un architettura che permette di sfruttare questa “pigrizia” per ottimizzare le risorse: invece che creare nuovi oggetti possiamo utilizzare l'attributo xtype, presente per ciascuna sottoclasse di Ext.Component per comunicare ad Ext quale è la tipologia di componente da creare. Sarà poi compito di Ext.ComponentMgr istanziare l'oggetto solo nel momento in cui esso è effettivamente necessario.

In questo esempio inseriremo un Ext.Panel all'interno di un altro Ext.Panel esterno. Grazie all'istanziazione lazy dovremmo occuparci solo di istanziare il pannello contenitore mentre il pannello figlio verrà costruito autonomamente dal framework.

<html>
	<head>
		<script src="../extjs/adapter/ext/ext-base.js"></script>
		<script src="../extjs/ext-all.js"></script>
		<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
		<script>
			Ext.onReady(function() {
				var p1 = new Ext.Panel({
					title: "Pannello 1",
					height: 300,
					width: 400,
					id:"panel1",
					items: {
						html: "contenuto del panel 2",
						title: "Pannello 2",
						id:"panel2",
						xtype: 'panel'
					}
				});
				p1.render(Ext.getBody());
			});
		</script>
	</head>
	<body>
	</body>
</html>

Questo approccio è molto consigliato anche dagli sviluppatori di ExtJS. L'elenco degli xtype disponibili è presente sulla documentazione ufficiale.

Ovviamente nel momento in cui si svilupperanno componenti ad hoc sarà possibile “mapparli” con il proprio xtype preferito tramite la chiamata statica Ext.ComponentMgr.registerType().

Le dirette sottoclassi di Ext.Component

Come abbiamo detto in precedenza, la classe Ext.Component è una classe astratta e quindi non deve essere istanziata direttamente. Per lavorare con i Component quindi dobbiamo agire sulle sue sottoclassi. ExtJS prevede 5 sottoclassi principali tra le quali la più importante è BoxComponent e la tratteremo successivamente. Oltre a Ext.BoxComponent abbiamo a disposizione:

  1. Ext.ColorPalette (xtype=colorpalette) che permette di creare pannelli per la selezione di un colore
  2. Ext.DatePicker (xtype=datepicker) che permette di creare pannelli per la selezione di date
  3. Ext.Editor (xtype=editor) che permette di creare campi di editing inline
  4. Ext.menu.BaseItem (classe astratta) che include funzionalità comuni a tutti gli elementi che possono essere inclusi in un menu

Tutti gli altri componenti complessi di ExtJS fanno capo a Ext.BoxComponent ovvero una superclasse di Ext.Component che rappresenta il punto di partenza per tutti quei widget grafici che possono essere racchiusi in un box con una altezza e larghezza personalizzabile e variabile. Questa classe si occupa infatti di eventuali aggiustamenti alle dimensioni del box-model e al posizionamento del widget in pagina. Qualsiasi BoxComponent può fare riferimento ad un particolare elemento HTML presente in pagina oppure crearne uno ad hoc nel caso non volessimo creare markup preventivo. Ecco un piccolo esempio:

<html>
	<head>
		<script src="../extjs/adapter/ext/ext-base.js"></script>
		<script src="../extjs/ext-all.js"></script>
		<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
		<script>
			Ext.onReady(function() {
				var empty = new Ext.BoxComponent({
					el: Ext.fly("box-component-div")
				});
				empty.update("BoxComponent");
				empty.setSize(300,400);
				var image = new Ext.BoxComponent({
					autoEl: {
						tag: "img",
						src: "https://www.html.it/common/img/html-logo.png"
					}
				});
				image.render(Ext.getBody());
			});
		</script>
	</head>
	<body>
		<div id="box-component-div"></div>
	</body>
</html>

Grazie alla proprietà el possiamo specificare un elemento HTML già esistente sul quale montare il BoxComponent mentre grazie alla proprietà autoEl possiamo specificare quale tag e quali attributi creare. Maggiori proprietà, metodi ed eventi sfruttabili sono disponibili sulle API ufficiali.

Lavorare a questo livello con i BoxComponent non è ancora molto efficace né premiante. La loro reale utilità verrà introdotta nel prossimo articolo quando approfondiremo un componente ancora più avanzato (Ext.Container) che ci permetterà di creare interfacce complesse e organizzate.


Ti consigliamo anche