domenica 9 maggio 2010

Template personalizzati in Struts2 con i .ftl


Quante volte ci sarà capitato a noi sviluppatori di montare nelle jsp la grafica che proviene da agenzie grafiche o da un web designer? Ovviamente grafica bellissima, con tanti effetti dinamici e contenuti al posto giusto. Ma più contenuti html, css, e js ci stanno e + aumenta il nostro lavoro e il nostro imprecare quando usiamo framework tipo struts, jsf e altri che hanno tag-library che magari renderizzano css e/o td pre impostati. Be ovviamente possiamo riscrivere le classi delle tag library.

Struts 2 invece ci viene incontro in questo.
Esso mette a disposizione dei file testuali con estensione ".ftl" . In questi file, tramite un linguaggio EL, è possibile personalizzare non solo i tag html da renderizzare ma il comportamento dei tag della tag library di struts 2. Il tutto in modo semplice e veloce.


Ogni tag può avere uno o più ftl associati e solitamente hanno come nome del file il nome del tag, ad esempio per il tag "s:a" ci sarà un "a.ftl".

L'insieme di tt questi .ftl sono contenuti nel jar di struts 2 sotto dei package dai path particolari.

Ad esempio gli ftl di default che usa struts 2 stanno nel package "template.xhtml", ma nel jar ne troviamo altri come "template.simple" ecc..

Ciò è importante poichè struts 2 va a cercare gli ftl proprio sotto "template" e i subpackage ne identificano il tipo o il raggruppamento o lo stile, diciamo il tema, scegliete voi come chiamarli.

Quindi per personalizzare i tag basta riscrivere gli ftl e posizionarli nei nostri sorgenti rispettando la convenzione dei nomi dei package indicando poi (in diversi modi a seconda di come vogliamo estenderli) a struts 2 quale tema utilizzare.

Continuando a sviluppare sull'applicazione di esempio dei precedenti post vi farò veder come fare passo dopo passo.

In questo post farò vedere come personalizzare la presentazione degli actionError, dei fieldsError e degli actionMessage, ma il discorso vale per tutti i tag di struts2. Nell'esempio estenderò il tema "simple" che è quello + semplice in quanto renderizza il minimo senza tabelle o div per disporre i contenuti a differenza di "xhtml".

Cominciamo con l'estrarre la cartella template/simple contenuta nello struts2-core.xxx.jar. Creiamo un package "template.tutorial" nei nostri sorgenti.
Come vedete ho dato il nome "tutorial" al nostro tema.

Copiate nel package tutti gli ftl contenuti nella cartella "simple" estratta.

La personalizzazione dei messaggi consiste nel far apparire un iconcina che identifica il tipo dei massaggi visualizzati, quindi un immagine info per i tag actionMessage e una di errore per gli actionError e i fieldError.

Ora aprite il file "actionmessage.ftl" del package creato, copiate il seguente codice, e rimpiazzatelo con il contenuto del file:



<#if (actionMessages?? && actionMessages?size > 0 && !parameters.isEmptyList)>

<div style="border:2px solid silver;">
<img src="img/info.png" width="30px" height="30px"/>&nbsp;&nbsp;&nbsp;<strong style="font-size:15px;">MESSAGGI INFORMATIVI</strong>



<ul<#rt/>
<#if parameters.id?if_exists != "">
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass??>
class="${parameters.cssClass?html}"<#rt/>
<#else>
class="actionMessage"<#rt/>
</#if>
<#if parameters.cssStyle??>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
>
<#list actionMessages as message>
<#if message?if_exists != "">
<li><span><#if parameters.escape>${message!?html}<#else>${message!}</#if></span></li>
</#if>
</#list>
</ul>

</div>

</#if>

in grassetto le righe che ho aggiunto rispetto all' "actionmessage.ftl" originale.
In pratica ho fatto questo.
Dopo che viene fatto il controllo (in linguaggio EL) se ci stanno messaggi e prima di essere renderizzato l'elenco dei messaggi tramite il tag html "ul" l'ho racchiusi in un div che renderizza un box con bordi grigi di 2 pixel e all'interno prima della lista dei messaggi l'immagine info.png con di fianco il testo MESSAGGI INFORMATIVI.

Stessa cosa per "actionerror.ftl":


<#if (actionErrors?? && actionErrors?size > 0)>

<div style="border:2px solid red;">
<img src="img/errore.png" width="30px" height="30px"/>&nbsp;&nbsp;&nbsp;<strong style="font-size:15px;">MESSAGGI DI ERRORE</strong>




<ul<#rt/>
<#if parameters.id?if_exists != "">
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass??>
class="${parameters.cssClass?html}"<#rt/>
<#else>
class="errorMessage"<#rt/>
</#if>
<#if parameters.cssStyle??>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
>
<#list actionErrors as error>
<#if error?if_exists != "">
<li><span><#if parameters.escape>${error!?html}<#else>${error!}</#if></span><#rt/></li><#rt/>
</#if>
</#list>
</ul>

</div>

</#if>

e "fielderror.ftl":

<#if fieldErrors??><#t/>
<#assign eKeys = fieldErrors.keySet()><#t/>
<#assign eKeysSize = eKeys.size()><#t/>
<#assign doneStartUlTag=false><#t/>
<#assign doneEndUlTag=false><#t/>
<#assign haveMatchedErrorField=false><#t/>
<#if (fieldErrorFieldNames?size > 0) ><#t/>
<#list fieldErrorFieldNames as fieldErrorFieldName><#t/>
<#list eKeys as eKey><#t/>
<#if (eKey = fieldErrorFieldName)><#t/>
<#assign haveMatchedErrorField=true><#t/>
<#assign eValue = fieldErrors[fieldErrorFieldName]><#t/>
<#if (haveMatchedErrorField && (!doneStartUlTag))><#t/>



<ul<#rt/>
<#if parameters.id?if_exists != "">
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass??>
class="${parameters.cssClass?html}"<#rt/>
<#else>
class="errorMessage"<#rt/>
</#if>
<#if parameters.cssStyle??>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
>
<#assign doneStartUlTag=true><#t/>
</#if><#t/>
<#list eValue as eEachValue><#t/>
<li><span>${eEachValue}</span></li>
</#list><#t/>
</#if><#t/>
</#list><#t/>
</#list><#t/>
<#if (haveMatchedErrorField && (!doneEndUlTag))><#t/>
</ul>



<#assign doneEndUlTag=true><#t/>
</#if><#t/>
<#else><#t/>
<#if (eKeysSize > 0)><#t/>


<div style="border:2px solid red;">
<img src="img/errore.png" width="30px" height="30px"/>&nbsp;&nbsp;&nbsp;<strong style="font-size:15px;">MESSAGGI DI ERRORE</strong>


<ul<#rt/>
<#if parameters.cssClass??>
class="${parameters.cssClass?html}"<#rt/>
<#else>
class="errorMessage"<#rt/>
</#if>
<#if parameters.cssStyle??>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
>
<#list eKeys as eKey><#t/>
<#assign eValue = fieldErrors[eKey]><#t/>
<#list eValue as eEachValue><#t/>
<li><span><#if parameters.escape>${eEachValue!?html}<#else>${eEachValue!}</#if></span></li>
</#list><#t/>
</#list><#t/>
</ul>

</div>


</#if><#t/>
</#if><#t/>
</#if><#t/>

solo che a differenza dell'ftl legato all'actionMessage agli altri ho cambiato il colore del riquadro in rosso e l'immagine con error.png.

Per completezza vi do anche la parte di css che ho cambiato o aggiunto nel file intro.css contenuto nella cartella WebContent/css:

....
div.areaMessaggi div{
margin-left:80px;
padding-top: 10px;
padding-left: 10px;
padding-right:10px;
max-width:400px;
border:2px solid silver;
}

.actionMessage{
color:green;
}


.errorMessage {
color:red;
}

ul.actionMessage li {
list-style-image: url(../img/li_ok.png);
}


ul.errorMessage li {
list-style-image: url(../img/li_ko.png);
}
...



il css non ve lo commento dato che non è il tema del tutorial.
Ovviamente mettete le immagini con i nomi che ho usato nella cartella WebContent/img.

Se scaricate il progetto cmq trovate tt pronto.

Non ci rimane che dire a struts 2 di utilizzare il nostro tema.

Per far ciò basta andare nello struts.xml e inserire la costante con il nome "struts.ui.theme" e valore il nome del raggruppamento, nel nostro caso:

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

[...]
<constant name="struts.ui.theme" value="tutorial" />
[...]

</struts>


vi ricordo che se non fate ciò struts continua usare quello di default che è "xhtml" contenuto nel suo jar.

Ovviamente sempre nello stesso modo potete configurare struts 2 per usare non uno nostro ma un'altro contenuto nel suo jar.

Se invece vogliamo estendere solo pochi ftl ad esempio per xhtml, basta creare il package

template.xhtml.pippo

Quindi mettere in quest'ultimo gli ftl e indicare nella jsp come attributo del tag quale template utilizzare ad esempio:



<s:actionmessage template="pippo"/>

senza modificare lo struts.xml.

Comunque per approfondimento sui template, tag e il linguaggio EL vi consiglio le guide ufficiali.
In questo post volevo solo farvi conoscere questa future di struts2.

Deploiate ed ecco il risultato in caso di actionMessage:

e in caso di messaggi di errore:

noterete che non appaiono + messaggi sulle caselle di input, questo poichè il tema "simple" non lo prevede.

Come al solito il progetto eclipse lo trovate QUI

2 commenti:

  1. ho provato il tuo programma su netbeans e non funziona...infatti non riconosce il template mi potresti aiutare?

    RispondiElimina
  2. Quale template? Comunque non penso che dipenda da netbeans.... RIvedi la configurazione nel file di struts, assicurati di aver configurato tt bene... e poi apri il pachetto generato da netbeans per il deploy (.war o .ear) e verifica che ci stia il tuo package "template.qualcosa" e che sia visibile dal class loader dell'application server.

    RispondiElimina