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

Icefaces JSF2: Ace Components

I componenti ACE (ICEFaces Advanced Components) sono componenti di ICEFaces che utilizzano tecniche di rendering sia lato server che lato client, per arricchire l'esperienza utente.
I componenti ACE (ICEFaces Advanced Components) sono componenti di ICEFaces che utilizzano tecniche di rendering sia lato server che lato client, per arricchire l'esperienza utente.
Link copiato negli appunti

I componenti ACE (ICEFaces Advanced Components) sono i componenti di ultima generazione di ICEFaces: oltre 40 componenti che utilizzano tecniche di rendering sia lato server che lato client, per fornire un'esperienza un'ottima esperienza utente.

Gli aspetti chiave possono essere sintetizzati in 3 punti:

  • Potenti componenti javascript (ad esempio jQuery), che sollevano lo sviluppatore dal loro utilizzo diretto.
  • Vasto supporto alle funzionalità client-side che migliorano i tempi di risposta e le potenzialità dei componenti.
  • Flessibile approccio alla creazione di temi grazie all'uso di jQuery e dei ThemeRoller themes.

In questo articolo continuiamo l'esplorazione inziata con l'articolo introduttivo sui componenti ICEFaces, esaminando stavolta alcuni componenti ACE, mantenendo un approccio pratico e semplice.

Il componente Accordion

L'accordion è un componente particolarmente utile per la costruzione di menu strutturati in pannelli che si aprono e chiudono mostrando contenuti

Per l'illustrazione di questo e di altri componenti, riprendiamo il nostro progetto ed il template di pagina del primo articolo. Costruiamo quindi una pagina accordion.xhtml ed inseriamo all'interno del tag form il codice per l'uso di esempio di questo componente:

<ace:accordion id="accordion" collapsible="true" autoHeight="false">
	<ace:accordionPane title="Title 1">
		<h:outputText value="item 1"/>
		<h:outputText value="item 2"/>
	</ace:accordionPane>
	<ace:accordionPane  title="Title 2">
		<h:outputText value="item 1"/>
		<h:outputText value="item 2"/>
	</ace:accordionPane>  
	<ace:accordionPane  title="Title 3">
		<h:outputText value="item 1"/>
		<h:outputText value="item 2"/>
	</ace:accordionPane>  
</ace:accordion>

Se eseguiamo la pagina possiamo visualizzare il componente in azione:

Icefaces Ace Accordion

Icefaces Ace Accordion

Come possiamo notare dal codice, il tag <ace:accordionPane/> ci permette di definire voci di primo livello, mentre suo interno possiamo inserire diverse tipologie di componenti: un link, un'immagine , una tabella, etc. Il componente ha diversi attributi da esplorare, provate ad esempio ad aggiungere in <ace:accordion ../> l'attributo effect con valore bounceslide, noterete un diverso comportamento grafico dell'accordion all'apertura delle voci di menù.

Il componente animation

ICEFaces fornisce un sistema di animazioni collegabili a molti componenti ACE. L'esempio che segue è tratto dallo showcase di ICEFaces e mostra tutti i possibili effetti applicabili.
L'esempio mostra diverse lettere, cliccando su ciascuna di esse possiamo scatenare diversi effetti grafici di animazione:

IceFaces ACE components: animation

IceFaces ACE components: animation

Per realizzarlo all’interno del nostro progetto, creiamo una pagina animation.xhtml usando il template ed inseriamo all'interno del tag form:

<h:panelGrid columns="5" width="100">
<h:panelGrid>
	<h:panelGrid>
		<h:outputText value="Blind Effect"/>
		<h:graphicImage id="blind" value="../resources/images/a-blue_small.png" alt="a-blue"/>
		<ace:animation event="click" name="blind"/>
		<ace:animation event="click" name="highlight"/>
	</h:panelGrid>
</h:panelGrid>
<h:panelGrid>
	<h:panelGrid>
		<h:outputText value="Fade Effect"/>
		<h:graphicImage id="fade" value="../resources/images/m-blue_small.png" alt="m-blue"/>
		<ace:animation event="click" name="fade" />
		<ace:animation event="click" name="highlight"/>
	</h:panelGrid>
</h:panelGrid>
[...]
<h:panelGrid>
	<h:panelGrid>
		<h:outputText value="Highlight Effect"/>
		<h:graphicImage id="highlight" value="../resources/images/o-black_small.png" alt="o-black"/>
		<ace:animation event="click" name="highlight"/>
	</h:panelGrid>
</h:panelGrid>
[...]
</h:panelGrid>

Guardando il codice è facile capire come funzioni il componente animation. Lo inseriamo all'interno del tag interessato, specifichiamo l'evento che fa scattare l'animazione (attributo event), nel nostro caso il click, ed infine definiamo con l'attributo name il tipo di animazione.

Il componente file Entry : File upload manager

Avere a disposizione un componente in grado di implementare facilmente le funzionalità di upload può essere molto utile: il File Entry ha numerosi attributi con i quali possiamo definire, ad esempio, percorso relativo alla web app o assoluto al file system di salvataggio del file, limitazioni sul numero di file in upload contemporaneo, dimensioni e cosi via…

L’esempio che segue è tratto dalle demo di ICEFaces, ma semplificato per l’uso all’interno del nostro progetto.
Realizziamo un semplice upload manager che in due step ci consente di inviare in upload un file. Vediamo subito l’immagine di ciò che andremo a realizzare:

IceFaces Ace Components: File Entry (upload manager)

IceFaces Ace Components: File Entry (upload manager)

Questa volta abbiamo bisogno di un managed bean da collegare al componente per gestire il processo di ricezione del file. Realizziamo una classe FileEntryManagedBean nel package it.html.icefaces del progetto, inseriamo quindi la definizione nel faces-config.xml:

<managed-bean>
	<managed-bean-name>fileEntryManagedBean</managed-bean-name>
	<managed-bean-class>it.html.icefaces.FileEntryManagedBean</managed-bean-class>
	<managed-bean-scope>view</managed-bean-scope>
</managed-bean>

Vogliamo gestire la lista dei file in upload attraverso una dataTable, definiamo quindi un campo per questa lista:

private List<String> fileData;

implementiamo il classico metodo get per questo campo.

Passiamo adesso al cuore della classe, la realizzazione del metodo di listener che gestisce il processo di upload. Questo metodo viene collegato al fileEntry attraverso l'attributo fileEntryListener e la sua definizione è la seguente:

public void sampleListener(FileEntryEvent e)

dove FileEntryEvent è una classe ICEFaces per la gestione dell'evento relativo a questo componente.
Vediamo invece adesso il codice da inserire all'interno di questo metodo: come prima operazione si recupera la lista dei file in upload:

FileEntry fe = (FileEntry)e.getComponent();
FileEntryResults results = fe.getResults();
File parent = null;

Si valorizza la lista per la dataTable

fileData = new ArrayList();

Si itera la lista dei file ottenuti dall'upload valorizzando anche la lista associata alla dataTable costruendo cosi un report finale di upload:

for (FileEntryResults.FileInfo i : results.getFiles()) {
	fileData.add("File Name: " + i.getFileName());
	if (i.isSaved()) {
		fileData.add("File Size: " + i.getSize() + " bytes");
		File file = i.getFile();
		if (file != null) {
			parent = file.getParentFile();
		}
	} else {
		fileData.add("File was not saved because: " + i.getStatus().getFacesMessage(FacesContext.getCurrentInstance(), fe, i).getSummary());
	}
}
if (parent != null) {
	long dirSize = 0;
	int fileCount = 0;
	for (File file : parent.listFiles()) {
		fileCount++;
		dirSize += file.length();
	}
	fileData.add("Total Files In Upload Directory: " + fileCount);
	fileData.add("Total Size of Files In Directory: " + dirSize + " bytes");
}

Il codice è relativamente semplice, ed è facile capire quanto lavoro faccia per noi il componente.
Abbiamo completato la parte logica del nostro mini sistema, realizziamo adesso la parte grafica partendo dal solito template all’interno del quale andiamo ad inserire il codice che segue, sempre all’interno del tag form:

<h:panelGrid>
	<h:outputText value="File Upload Manager" />
</h:panelGrid>
<ace:panel style="font-size:11px;width:650px">
	<h:panelGrid columns="3" >
		<h:panelGrid>
			<h:panelGrid ><h:outputText value="Step 1" /></h:panelGrid>
			<ace:panel style="width: 250px; height: 40px; border: 0px;">
			<ace:fileEntry id="File-uploader"
				relativePath="/files/" maxFileCount="1"
				maxFileCountMessage="Limited to 1 files uploaded concurrantly."
                                fileEntryListener="#{fileEntryManagedBean.sampleListener}"
				maxFileSize="6291456" maxFileSizeMessage="Submitted file is too large."
				maxTotalSize="18874368" maxTotalSizeMessage="Total size of submitted files is too large."
				required="true" requiredMessage="The file is required to submit this form."
				useOriginalFilename="true" useSessionSubdir="true" />
			</ace:panel>
		</h:panelGrid>
		<h:panelGrid width="100%" >
			<h:graphicImage value="/resources/images/navigateForward.png" />
		</h:panelGrid>
		<h:panelGrid width="100%">
			<h:panelGrid><h:outputText value="Step 2"/></h:panelGrid>
				<ace:panel style="width: 100px; height: 30px; border: 0px;">
					<h:commandButton id="submit" type="submit" value="Send File"/>
				</ace:panel>
			</h:panelGrid>
		</h:panelGrid>
                <br/>
                <hr/>
                <br/>
		<h:dataTable id="tbl" value="#{fileEntryManagedBean.fileData}" var="fileDataVal">
			<h:column>
				<f:facet name="header"><h:outputText value="Upload results"/></f:facet>
				<h:outputText id="fileData" value="#{fileDataVal}"/>
			</h:column>
                </h:dataTable>
		<h:messages id="msgs" layout="table" for="File-Uploader"/>
</ace:panel>

Nel tag del componente ace:fileEntry notiamo numerosi attributi tra cui:

il collegamento al nostro listener di gestione

fileEntryListener="#{fileEntryManagedBean.sampleListener}"

il path di salvataggio del file

relativePath=”/files/”
in questo caso si è specificato un path relativo alla root della web application ma esiste anche l'attributo absolutePath per specificare un percorso del file system

attributi per dimensione e quantità dei file

Gli attributi che iniziano per max consento di definire limitazioni su numero e dimensioni di file:
useOriginalFilename imposta o meno l'uso del nome del file nel salvataggio, useSessionSubdir invece ci fornisce la possibilità di salvare i file in sottocartelle con il nome ricavato dalla sessione dell'’utente.

I componenti drag & drop

Concludiamo il nostro viaggio negli ACE components con i componenti ace:draggable ed ace:droppable ed il loro uso con la dataTable.

Prendendo spunto dall'esempio dello showcase realizziamo un carello della spesa con tecnica drag & drop: selezioniamo gli elementi che intendiamo acquistare trascinandoli e rilasciandoli poi in una determinata area. Vediamo subito immagini relative al funzionamento:

Per questo esempio abbiamo bisogno di una classe (nel package it.html.icefaces) per gli item davvero molto semplice di cui mostriamo immediatamente il codice:

public class Item {
	private String picture;
	private String description;
	private String type;
	private int price;
      . . . . // get and set methods
}

Dobbiamo inoltre definire un managed bean:

public class DataTableDragDropManagedBean {
	private List<Item> availableItems;
	private List<Item> purchasedItems;
	@PostConstruct
	private void initializeData() {
		availableItems = new ArrayList<Item>();
		int price=10;
		Item item = new Item();
			item.setType("electronic device");
			item.setDescription("Laptop");
			item.setPrice(price);
			item.setPicture("/resources/images/laptop.png");
			price+=10;
		availableItems.add(item);
	// [...]	            
	purchasedItems = new ArrayList<Item>();
}
public void handleDrop(DragDropEvent e){
	Item item = (Item)e.getData();
	purchasedItems.add(item);
	availableItems.remove(item);
}
// get/set AvailableItems
// get/set PurchasedItems
}

La classe ha come obiettivo quello di gestire le liste di elementi disponibili (availableItems) e di quelli che si intendono acquistare (purchasedItems).
Con il metodo initializeData() inizializziamo la lista di elementi disponibili con items di esempio per la nostra demo.
Il metodo

public void handleDrop(DragDropEvent e)

è ciò che ci consente di gestire l'evento di rilascio dell'elemento trascinato nell'area sensibile al drop.

In questo metodo ricaviamo l'elemento selezionato, lo aggiungiamo alla lista di quelli acquistati, e lo rimuoviamo da quelli disponibili. Per quanto riguarda il codice il nostro lavoro è completato: proseguiamo quindi realizzando l'interfaccia vista in precedenza.

Come è ormai nostra abitudine, riprendiamo la nostra pagina template ed inseriamo all'interno del tag form il seguente codice ICEFaces:

<ace:dataTable
	id="shoppingList" value="#{dataTableDragDropManagedBean.availableItems}"
	var="availableItem" style="width:500px">
<ace:column headerText="Picture">
	<h:graphicImage id="itemImg" value="#{availableItem.picture}">
	<ace:draggable revert="true" stack=".imageStyle" opacity="0.7"/>
	</h:graphicImage>
</ace:column>
<ace:column headerText="Description">
	<h:outputText id="description" value="#{availableItem.description}"/>
</ace:column>
<ace:column headerText="Type">
	<h:outputText id="type" value="#{availableItem.type}"/>
</ace:column>
<ace:column headerText="Price">
	<h:outputText id="price" value="#{availableItem.price}"/>
</ace:column>
</ace:dataTable>

In questa prima porzione è presente la dataTable degli elementi disponibili. È estremamente interessante notare come la funzionalità di drag venga realizzata semplicemente inserendo all'interno del componente graphicImage il componente ace:draggable.

<ace:panel id="shoppingCart" header="Shopping Cart"  style="display: block; font-size: 12pt;width:500px">
<h:outputText id="cartText"
	value="Shop with confedence ! To begin drag any item image above to the shopping cart."
	rendered="#{empty dataTableDragDropManagedBean.purchasedItems}"/>
<ace:dataTable id="purchasedItems"
	value="#{dataTableDragDropManagedBean.purchasedItems}" var="item"
	rendered="#{not empty dataTableDragDropManagedBean.purchasedItems}">
	<ace:column headerText="Description">
		<h:outputText id="name" value="#{item.description}"/>
	</ace:column>
	<ace:column headerText="Type">
		<h:outputText id="type" value="#{item.type}"/>
	</ace:column>
	<ace:column headerText="Price">
		<h:outputText id="price" value="#{item.price}"/>
	</ace:column>
</ace:dataTable>
<ace:droppable tolerance="touch"
	datasource="shoppingList"
	dropListener="#{dataTableDragDropManagedBean.handleDrop}"
	activeStyleClass="slot">
	<ace:ajax execute="@this" render="shoppingCart shoppingList" />
</ace:droppable>
</ace:panel>

La lista degli elementi da acquistare è ancora una volta una datasource, che contiene però al suo interno il componente ace:droppable collegato al listener di gestione.

Dobbiamo inoltre notare come venga collegato alla datasource di partenza attraverso l'attributo datasource. Si può inoltre evidenziare come venga fatto uso del componente ajax per il refresh della datasource di partenza e del panel che contiene la dataTable di destinazione.

Infatti l'operazione drag & drop realizzata utilizza ajax, e se non utilizzassimo delle chiamate di render per aggiornare lo stato dei componenti, non vedremmo alcun risultato.

Conclusioni

Abbiamo visto alcuni interessanti componenti ACE e preso familiarità con essi realizzando alcuni semplici esempi.

Vi sono molti altri componenti da esplorare e testare ed il consiglio è sicuramente quello di farlo approfittando della buona documentazione a disposizione sul sito di ICEFaces: il prossimo passo è quello di mettere in pratica le nostre conoscenze per realizzare qualcosa di più vicino alle problematiche reali attraverso l'implementazione di una web application che faccia uso di ICEFaces.

Ti consigliamo anche