Cómo crear Widgets por composición en wuija
0. Índice de contenidos.
1. Introducción
En este pequeño tutorial se pretende clarificar un poco cómo se crearían nuevos componentes visuales para wuija utilizando los ya existentes.
Pongamos que queremos crear un componente que permita insertar un rango de fechas, es decir una fecha «desde» y una fecha «hasta». En wuija tenemos ya un componente fecha que se llama DateProperty.
Sería el de la siguiente imagen:
Nuestro nuevo componente se va a llamar DateBetween, y va a ser una composición de dos DateProperty y dos OutputText, para que salgan el «hasta» y el «desde».
Debería quedar de la siguiente forma:
2. Creando la vista principal
Nuestro componente se va a mostrar en un formulario con otros campos, otros widgets, y otros componentes de Icefaces. Lo que vamos a hacer es montar nuestra vista y agregar nuestro widget DateBetween.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="UTF-8"?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:ice="http://www.icesoft.com/icefaces/component" xmlns:tnt="http://www.autentia.com/frmwrk/component"> <ui:composition> <ice:form id="globalForm"> ... <tnt:widget childWidget="#{globalForm.dateBetween}" /> ... |
A esta vista la vamos a llamar globalForm.jspx y le vamos a asociar un controlador GlobalForm.java. Si nos fijamos, la línea 13 es la que contiene nuestro componente de wuija. globalForm haría referencia a nuestro Controlador y dateBetween hace referencia al widget.
Lo que estamos diciendo hasta ahora es que nuestro controlador como mínimo va a tener dentro un Widget
del tipo DateBetween, y unos getters/setters para acceder a él. Eso es lo que implica esa línea. Aún no sabemos cómo se va a pintar nuestro componente ni cómo está formado, pero vayamos por partes.
3. Creando el Widget DateBetween
Cómo ya hemos dicho este componente va a ser una composición de dos DateProperty. Pero, ¿qué es un DateProperty?. Un DateProperty es un Widget de wuija que nos permite pintar un campo para recoger una fecha, es decir, esto: DateProperty hereda de Property.java, que a su vez hereda de JsfWidget.java.
Si miramos dentro de DateProperty al final vemos que lo que pinta es un ice:selectInputDate, es decir el componente de Icefaces para recoger fechas, sólo que además tenemos funcionabilidad extra. Todo Widget debe heredar de JsfWidget. Esto aporta funcionabilidad al Widget. No es el objetivo de este tutorial explicar esta clase, porque podemos perder el foco de lo que estamos haciendo.
Basta con decir que al extender de esta clase estamos implementando métodos que nos pueden servir para por ejemplo:
- Poder vincular Roles específicos asociados al Widget
- Saber si el Widget está activo o no.
- Añadir un Listener
- …ver la clase para más imformación…
Además al extender de JsfWidget estamos obligados a implementar el método getRendererPath. Si lo juntamos todo nos tendría que quedar un Widget más o menos como lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
public class DateBetween extends JsfWidget { private Date dateInit; private Date dateEnd; private DateProperty dateInitProperty; private DateProperty dateEndProperty; public DateBetween() { setDateInitProperty(new DateProperty(this.getClass(), "dateInit", true)); setDateEndProperty(new DateProperty(this.getClass(), "dateEnd", true)); this.dateEnd = new Date(); } public Date getDateInit() { return dateInit; } public void setDateInit(Date dateInit) { this.dateInit = dateInit; } public Date getDateEnd() { return dateEnd; } public void setDateEnd(Date dateEnd) { this.dateEnd = dateEnd; } public void setDateInitProperty(DateProperty dateInitProperty) { this.dateInitProperty = dateInitProperty; } public DateProperty getDateInitProperty() { return dateInitProperty; } public void setDateEndProperty(DateProperty dateEndProperty) { this.dateEndProperty = dateEndProperty; } public DateProperty getDateEndProperty() { return dateEndProperty; } @Override public String getRendererPath() { return RENDERER_PATH + "inputDateBetween.jspx"; } } |
Si nos fijamos un poco (lineas 7 y 9) vemos que este componente está formado por dos DateProperty, que era lo que ya teníamos. A esto se le llama hacer un componente por composición. Me creo uno nuevo a partir de otros.
Como vemos nuestra clase extiende de JsfWidget, por lo tanto implementa (linea 45-48) getRendererPath(). Aquí es donde le estamos diciendo cómo se va a pintar este componente. Los DateProperty (dateInitProperty y dateEndProperty) también tendrán su propio getRendererPath pues también son Widgets, y si navegáis hacia ellos veréis cómo lo que se está pintando al final es un ice:selectInputDate.
Como véis también tenemos dos fechas de tipo Date. Es aquí donde vamos a guardar los valores que el usuario introduzca por pantalla. En el constructor del Widget vemos que lo que estamos haciendo es inicializar cada uno de los Widget de los que éste está compuesto. De nuevo, no se van a explicar cómo están implementados los constructores específicos de los DateProperty, pues son
componentes que teníamos de antes y el objetivo de este tutorial es explicar cómo se podrían montar nuevos componentes. Lo que sí tenemos que hacer es un constructor para nuestro nuevo componente (línea 11) en donde inicializamos los Widgest que lo componen y además por ejemplo ponemos la fecha «hasta» a día de hoy (línea 14).
También deberemos implementar los getters y setters para acceder a toda la información contenida en este widget (los dos dateProperty y las dos fechas).
3.1 ¿Cómo se pinta el nuevo Widget?
Precisamente la clase JsfWidget obliga a implementar getRendererPath() para indicarle al widget cómo debe pintarse. Si nos fijamos, nuestro nuevo Widget contenía en esa función inputDateBetween.jspx. Vamos a ver qué contendría esta vista.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright 2008 Autentia Real Business Solutions S.L. This file is part of Autentia WUIJA. Autentia WUIJA is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. Autentia WUIJA is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Autentia WUIJA. If not, see <http://www.gnu.org/licenses/>. --> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:ice="http://www.icesoft.com/icefaces/component" xmlns:tnt="http://www.autentia.com/frmwrk/component"> <ui:component> <ice:panelGrid columns="2"> <h:panelGroup> <ice:outputText value="#{msg['inputDateBetween.from']}" /> <tnt:widget childWidget="#{widget.dateInitProperty}"> <ui:param name="value" value="#{widget}" /> </tnt:widget> </h:panelGroup> <h:panelGroup> <ice:outputText value="#{msg['inputDateBetween.to']}" /> <tnt:widget childWidget="#{widget.dateEndProperty}"> <ui:param name="value" value="#{widget}" /> </tnt:widget> </h:panelGroup> </ice:panelGrid> </ui:component> </jsp:root> |
Si nos fijamos a partir de la línea 27 lo que tenemos es un panel de 2 columnas. En la primera columna hemos agrupado el «desde» (ice:outputText value=»#{msg[‘inputDateBetween.from’]}») y un DateProperty (tnt:widget childWidget=»#{widget.dateInitProperty}»). Este DateProperty es un widget, luego lo tenemos que declarar así. Widget está haciendo referencia a nuestro Widget DateBetween, que si os fijáis contiene un atributo dateInitProperty, que es un DateProperty, al cual podrá acceder porque tiene getter y setter.
Para el hasta lo haríamos igual. Con esto tendríamos hecha la vista y habríamos terminado nuestro Widget.
Espero que os haya sido de utilidad !!