openxava / documentación / Personalización

Guía de referencia: Modelo | Vista | Datos tabulares | Mapeo objeto/relacional | Controladores | Aplicación | Personalización

Tabla de contenidos

Personalización
Editores
Configuración de editores
Editores para valores múltiples
Editores para referencias (nuevo en v3.1.3)
Editores para colecciones (nuevo en v3.1.3)
Editores para tabs (modo lista) (nuevo en v4.6)
Editores para formatos de lista (nuevo en v5.7)
Editores para formatos de lista en entidades específicas (nuevo en v7.3)
Editores para anotaciones (nuevo en v6.6)
JavaScript en los editores
A partir de v4m3
Hasta v4m2
Until 3.0.x
CSS en editores (nuevo en v5.4)
Editores personalizables y estereotipos para crear combos
Vistas JSP propias y taglibs de OpenXava
Ejemplo
xava:editor
xava:action, xava:link, xava:image, xava:button
xava:message (nuevo en v2.0.3)
xava:label (nuevo en v5.5)
xava:descriptionsList (nuevo en v2.0.3)
Modificar el código JSP del núcleo de OpenXava
Configuración de propiedades en xava.properties
La interfaz de usuario generada por OpenXava es buena para la mayoría de los casos, pero a veces puede que necesitemos personalizar alguna parte de la interfaz de usuario (creando nuestros propios editores) o crear nuestra interfaz de usuario íntegramente a mano (usando vistas personalizadas con JSP).
Por otra parte, si simplemente quieres definir la apariencia visual de tu aplicación, mira la guía para definir un Estilo visual personalizado.

Editores

Configuración de editores

Vemos como el nivel de abstracción usado para definir las vista es alto, nosotros especificamos las propiedades que aparecen y como se distribuyen, pero no cómo se visualizan. Para visualizar las propiedades OpenXava utiliza editores.
Un editor indica como visualizar una propiedad. Consiste en una definición XML junto con un fragmento de código JSP.
Para refinar el comportamiento de los editores de OpenXava o añadir los nuestros podemos crear en el directorio src/main/resources/xava (xava en v6 o anteriores) de nuestro proyecto un archivo llamado editores.xml. Este archivo es como sigue:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
 
<!DOCTYPE editores SYSTEM "dtds/editores.dtd">
 
<editores>
 <editor .../> ...
</editores>
Simplemente contiene la definición de un conjunto de editores, y un editor se define así:
<editor
    nombre="nombre"                         <!--  1  Nuevo en v2.1.3 -->
    url="url"                               <!--  2 -->
    formatear="true|false"                  <!--  3 -->
    depende-de-estereotipos="estereotipos"  <!--  4 -->
    depende-de-propiedades="propiedades"    <!--  5 -->
    enmarcable="true|false"                 <!--  6 -->
    recargar-siempre="true|false"           <!--  7  Nuevo en v3.1.2 -->
    compuesto="true|false"                  <!--  8  Nuevo en v3.1.3 -->
    icono="icono"                           <!--  9  Nuevo en v5.7 -->
    accion-iniciar="Controlador.accion"     <!-- 10  Nuevo en v5.7 -->
    accion-liberar="Controlador.accion"     <!-- 11  Nuevo en v5.7 -->
    elementos-seleccionables="true|false"   <!-- 12  Nuevo en v5.7 -->
>
   <propiedad ... /> ...                    <!-- 13 -->
   <formateador ... />                      <!-- 14 -->
   <formateador-lista ... />                <!-- 15  Nuevo en v3.1.4 -->
   <para-estereotipo ... /> ...             <!-- 16 -->
<para-anotacion ... /> ... <!-- 17 Nuevo en v6.6 -->
 <para-tipo ... /> ... <!-- 18 --> <para-propiedad-modelo ... /> ... <!-- 19 --> <para-referencia ... /> ... <!-- 20 Nuevo en v3.1.3 --> <para-coleccion ... /> ... <!-- 21 Nuevo en v3.1.3 --> <para-tab ... /> ... <!-- 22 Nuevo en v4.6 --> <para-valores-posibles /> <!-- 23 Nuevo en v2.1.2 --> <para-referencias /> <!-- 24 Nuevo en v3.1.3 --> <para-colecciones /> <!-- 25 Nuevo en v3.1.3 --> <para-colecciones-elementos /> <!-- 26 Nuevo en v5.0 --> <para-tabs /> <!-- 27 Nuevo en v4.6 --> </editor>
  1. nombre (opcional): (Nuevo en v2.1.3) Nombre para referenciar a este editor desde otros sitios, por ejemplo desde @Editor en una entidad JPA o desde <vista-referencia ... editor=/> desde un componente XML.
  2. url (obligado): URL de la página JSP que implementa el editor. Empieza desde xava/editors (dentro de la carpeta src/main/webapp de nuestro proyecto, simplemente web antes de v7).
  3. formatear (opcional): Si es true es OpenXava el que tiene la responsabilidad de formatear los datos desde HTML hasta Java y viceversa, si vale false tiene que hacerlo el propio editor (generalmente recogiendo información del request y asignandolo a org.openxava.view.View y viceversa). Por defecto vale true.
  4. depende-de-estereotipos (opcional): Lista de estereotipos separados por comas de los cuales depende este editor. Si en la misma vista hay algún editor para estos estereotipos éstos lanzarán un evento de cambio si cambian.
  5. depende-de-propiedades (opcional): Lista de propiedades separadas por comas de los cuales depende este editor. Si en la misma vista se está visualizando alguna de estas propiedades éstas lanzarán un evento de cambio si cambian.
  6. enmarcable (opcional): Si vale true enmarca visualmente el editor. Por defecto vale false. Es útil para cuando hacemos editores grandes (de más de una línea) que pueden quedar más bonitos de esta manera.
  7. recargar-siempre (opcional): (Nuevo en v3.1.2) Si es true, este editor se recarga siempre (cada vez que el usuario ejecuta una acción o hace cualquier otra petición a la aplicación). Cuando vale false el editor solo se recarga cuando el dato que está representado ha sido cambiado. Por defecto vale false.
  8. compuesto (opcional): (Nuevo en v3.1.3) Una editor compuesto está formado por otros editores; recibe un objeto View que reepresenta una subvista. Por defecto vale false.
  9. icono (opcional): (Nuevo en v5.7) Id de un icono de Material Design Icons. Por ejemplo, si escribes icono="bell" un campana se usará como icono para permitir al usuario escoger el editor. Actualmente escoger un editor sólo está disponible en modo lista.
  10. accion-iniciar (opcional) (Nuevo en v5.7): Nombre calificado de la acción (de controladores.xml) para iniciar el editor. Actualmente aplica solo a editores de modo lista.
  11. accion-liberar (opcional) (Nuevo en v5.7): Nombre calificado de la acción (de controladores.xml) para liberar los recursos usados por el editor. Actualmente aplica sólo a editores de modo lista.
  12. elementos-seleccionables (opcional) (Nuevo en v5.7): Si true, el editor permite al usuario seleccionar varios elementos (con casillas de verificación o similares). De esta manera OpenXava puede saber cuando ocultar las acciones que procesan varios elementos. Actualmente aplica sólo a editores de modo lista. Por defecto vale true.
  13. propiedad (varias, opcional): Permite enviar valores al editor, de esta forma podemos configurar un editor y poder usarlo en diferente situaciones.
  14. formateador (uno, opcional): Clase java para definir la conversión de Java a HTML y de HTML a Java.
  15. formateador-lista (uno, opcional): (Nuevo en v3.1.4) Clase java para definir la conversión de Java a HTML en modo lista.
  16. para-estereotipo (varias, opcional): Asocia este editor a un estereotipo. La preferencia es: un editor a una propiedad de un modelo, después por estereotipo, después por anotación y como último por tipo.
  17. para-anotacion (varias, opcional): (Nuevo en v6.6) Asocia este editor a una anotación Java. La preferencia es: un editor a una propiedad de un modelo, después por estereotipo, después por anotación y como último por tipo.
  18. para-tipo (varias, opcional): Asocia este editor a un tipo. La preferencia es: un editor a una propiedad de un modelo, después por estereotipo, después por anotación y como último por tipo.
  19. para-propiedad-modelo (varias, opcional): Asocia este editor a una propiedad concreta de un modelo. La preferencia es: un editor a una propiedad de un modelo, después por estereotipo, después por anotación y como último por tipo.
  20. para-referencia (varios, opcional): (Nuevo en v3.1.3) Este editor se usará para las referencias al modelo especificado.
  21. para-coleccion (varios, opcional): (Nuevo en v3.1.3) Este editor se usará para las colecciones de objetos del modelo especificado.
  22. para-tab (varios, opcional): (Nuevo en v4.6) Este editor se usará para los tabs (modo lista) de objetos del modelo especificado.
  23. para-valores-posibles (uno, opcional): (Nuevo en v2.1.2) Este será el editor por defecto para enum y <valores-posibles/>.
  24. para-referencias (uno, opcional): (Nuevo en v3.1.3) Este será el editor por defecto para las referencias.
  25. para-colecciones (uno, opcional): (Nuevo en v3.1.3) Este será el editor por defecto para las colecciones.
  26. para-colecciones-elementos (uno, opcional): (Nuevo en v5.0) Este será el editor por defecto para las colecciones de elementos (@ElementCollection).
  27. para-tabs (uno, opcional): (Nuevo en v4.6) Este será el editor por defecto para los tabs, es decir para el modo lista.
Podemos ver un ejemplo de definición de editor, este ejemplo es uno de los editores que vienen incluidos con OpenXava, pero es un buen ejemplo para aprender como hacer nuestros propios editores:
<editor url="textEditor.jsp">
 <for-type type="java.lang.String"/>
 <for-type type="java.math.BigDecimal"/>
 <for-type type="int"/>
 <for-type type="java.lang.Integer"/>
 <for-type type="long"/>
 <for-type type="java.lang.Long"/>
</editor>
Aquí asignamos a un grupo de tipos básicos el editor textEditor.jsp (podemos encontrarlo en openxava/src/main/resources/META-INF/resources/xava/editors). El código JSP de este editor es:
<%@ page import="org.openxava.model.meta.MetaProperty" %>
 
<%
String propertyKey = request.getParameter("propertyKey"); // 1
MetaProperty p = (MetaProperty) request.getAttribute(propertyKey); // 2
String fvalue = (String) request.getAttribute(propertyKey + ".fvalue"); // 3
String align = p.isNumber()?"right":"left"; // 4
boolean editable="true".equals(request.getParameter("editable")); // 5
String disabled=editable?"":"disabled"; // 5
String script = request.getParameter("script"); // 6  Ignorado desde v7.2, por lo que ya no es necesario
boolean label = org.openxava.util.XavaPreferences.getInstance().isReadOnlyAsLabel();
if (editable || !label) { // 5
%>
<input id="<%=propertyKey%>" name="<%=propertyKey%>" class=editor <!-- 1 -->
 type="text"
 tabindex="1" <!-- 7 -->
 title="<%=p.getDescription(request)%>"
 align='<%=align%>' <!-- 4 -->
 maxlength="<%=p.getSize()%>"
 size="<%=p.getSize()%>"
 value="<%=fvalue%>" <!-- 3 -->
 <%=disabled%> <!-- 5 -->
 <%=script%> <!-- 6  Ignorado desde v7.2 -->
 />
<%
} else {
%>
<%=fvalue%>&nbsp;
<%
}
%>
<% if (!editable) { %>
 <input type="hidden" name="<%=propertyKey%>" value="<%=fvalue%>">
<% } %>
Un editor JSP recibe un conjunto de parámetros y tiene accesos a atributos que le permiten configurarse adecuadamente para encajar bien en una vista OpenXava. En primer lugar vemos como cogemos propertyKey (1) que después usaremos como id HTML. A partir de ese id podemos acceder a la MetaProperty (2) (que contiene toda la meta información de la propiedad a editar). El atributo fvalue(3) contiene el valor ya formateado y listo para visualizar. Averiguamos también la alineación (4) y si es o no editable (5). También recibimos el trozo de script de javascript (6) que hemos de poner en el editor (a partir de v7.2 no tienes que especificar script, es ignorado).
Hemos de especificar tabindex="1" (7) para que el editor aparezca en el orden correcto de tabulación (nuevo en v4.5.1).
Para tus propios editores el archivo JSP tiene que estar en la carpeta src/main/webapp/xava/editors (web/xava/editors en v6 o anterior) de tu proyecto, si la carpeta no existe aún, creala.
Aunque crear un editor directamente con JSP es sencillo no es una tarea muy habitual, es más habitual configurar JSPs ya existentes. Por ejemplo si en nuestro editores.xml en src/main/resources/xava (simplemente xava antes de v7) ponemos:
<editor url="textEditor.jsp">
 <formatedor clase="org.openxava.formatters.UpperCaseFormatter"/>
 <para-tipo tipo="java.lang.String"/>
</editor>
Estaremos sobreescribiendo el comportamiento de OpenXava para las propiedades de tipo String, ahora todas las cadenas se visualizaran y aceptaran en mayúsculas. Podemos ver el código del formateador:
package org.openxava.formatters;
 
import javax.servlet.http.*;
 
/**
 * @author Javier Paniza
 */
 
public class UpperCaseFormatter implements IFormatter { // 1
 
 public String format(HttpServletRequest request, Object string) { // 2
 return string==null?"":string.toString().toUpperCase();
 }
 
 public Object parse(HttpServletRequest request, String string) { // 3
 return string==null?"":string.toString().toUpperCase();
 }
 
}
Un formateador ha de implementar IFormatter (1) o IMetaPropertyFormatter (nuevo en v5.9) lo que lo obliga a tener un método format() (2) que convierte el valor de la propiedad que puede ser un objeto Java cualquiera en una cadena para ser visualizada en un documento HTML; y un método parse() (3) que convierte la cadena recibida de un submit del formulario HTML en un objeto Java listo para asignar a la propiedad.
También podemos establecer un formateador especifico para modo lista (Nuevo en v3.1.4), para esto disponemos de formateador-lista. El formateador asignado a este atributo nos indicará la forma en la cual se visualizará la información en el modo lista sin afectar al modo detalle. Este formateador implementará IFormatter pero a diferencia del anterior solo será necesario implementar format(). Si no se especifica formateador-lista los datos de la lista son formateados con formateador.

Editores para valores múltiples

Definir un editor para editar valores múltiples es parecido a hacerlo para valores simples. Veamos.
Por ejemplo, si queremos definir un estereotipo REGIONES que permita al usuario seleccionar más de una región para una propiedad. Ese estereotipo se puede usar de esta manera:
@Stereotype("REGIONES")
private String [] regiones;
Entonces podemos añadir una entrada en el archivo tipo-estereotipo-defecto.xml como sigue:
<para estereotipo="REGIONES" tipo="String []"/>
Y definir nuestro editor en el editores.xml de nuestro proyecto:
<editor url="editorRegiones.jsp"> <!-- 1 -->
 <propiedad nombre="cantidadRegiones" valor="3"/> <!-- 2 -->
 <formateador clase="org.openxava.formatters.MultipleValuesByPassFormatter"/> <!-- 3 -->
 <para-estereotipo estereotipo="REGIONES"/>
</editor>
editorRegiones.jsp (1) es el archivo JSP que dibuja nuestro editor. Podemos definir propiedades que serán enviada al JSP como parámetros del request (2). El formateador tiene que implementar IMultipleValuesFormatter, que es similar a IFormatter pero usa String [] en vez de String. En este caso usamos un formateador genérico que simplemente deja pasar el dato.
Y para terminar escribimos nuestro editor JSP en la carpeta src/main/webapp/xava/editors (web/xava/editors en v6 o anterior) de tu proyecto:
<%@ page import="java.util.Collection" %>
<%@ page import="java.util.Collections" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="org.openxava.util.Labels" %>
 
<jsp:useBean id="style" class="org.openxava.web.style.Style" scope="request"/>
 
<%
String propertyKey = request.getParameter("propertyKey");
String [] fvalues = (String []) request.getAttribute(propertyKey + ".fvalue"); // (1)
boolean editable="true".equals(request.getParameter("editable"));
String disabled=editable?"":"disabled";
String script = request.getParameter("script"); // Ignorado desde v7.2, ya no es necesario 
boolean label = org.openxava.util.XavaPreferences.getInstance().isReadOnlyAsLabel();
if (editable || !label) {
 String sregionsCount = request.getParameter("cantidadRegiones");
 int regionsCount = sregionsCount == null?5:Integer.parseInt(sregionsCount);
 Collection regions = fvalues==null?Collections.EMPTY_LIST:Arrays.asList(fvalues);
%>
<select id="<%=propertyKey%>" name="<%=propertyKey%>" multiple="multiple"
 class=<%=style.getEditor()%>
 <%=disabled%>
 <%=script%>> <!-- No se usa desde v7.2 -->
 <%
 for (int i=1; i<regionsCount+1; i++) {
 String selected = regions.contains(Integer.toString(i))?"selected":"";
 %>
 <option
 value="<%=i%>" <%=selected%>>
 <%=Labels.get("regions." + i, request.getLocale())%>
 </option>
 <%
 }
 %>
</select>
<%
}
else {
 for (int i=0; i<fvalues.length; i++) {
%>
<%=Labels.get("regions." + fvalues[i], request.getLocale())%>
<%
 }
}
%>
 
<%
if (!editable) {
 for (int i=0; i<fvalues.length; i++) {
%>
 <input type="hidden" name="<%=propertyKey%>" value="<%=fvalues[i]%>">
<%
 }
}
%>
Como se puede ver es como definir un editor para un valor simple, la principal diferencia es que el valor formateado (1) es un array de cadenas (String []) y no una cadena simple (String).
Como alternativa, puedes definir el editor anterior usando casillas de verificación (checkboxes) (nuevo en v4.9), como sigue:
<%@ page import="java.util.Collection" %>
<%@ page import="java.util.Collections" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="org.openxava.util.Labels" %>
 
<jsp:useBean id="style" class="org.openxava.web.style.Style" scope="request"/>
 
<%
String propertyKey = request.getParameter("propertyKey");
String [] fvalues = (String []) request.getAttribute(propertyKey + ".fvalue");
boolean editable="true".equals(request.getParameter("editable"));
String disabled=editable?"":"disabled";
String script = request.getParameter("script"); // Ignorado desde v7.2, ya no es necesario 
boolean label = org.openxava.util.XavaPreferences.getInstance().isReadOnlyAsLabel();
if (editable || !label) {
    String sregionsCount = request.getParameter("cantidadRegiones");
    int regionsCount = sregionsCount == null?5:Integer.parseInt(sregionsCount);
    Collection regions = fvalues==null?Collections.EMPTY_LIST:Arrays.asList(fvalues);
    for (int i=1; i<regionsCount+1; i++) {
        String checked = regions.contains(Integer.toString(i))?"checked":"";
    %>
        <input name="<%=propertyKey%>" type="checkbox" class="<%=style.getEditor()%>"
                tabindex="1"
                value="<%=i%>"
                <%=checked%>
                <%=disabled%>
                <%=script%> <!-- No se usa desde v7.2 -->
        />
        <%=Labels.get("regions." + i, request.getLocale())%>
    <%
    }
}
else {
    for (int i=0; i<fvalues.length; i++) {
%>
<%=Labels.get("regions." + fvalues[i], request.getLocale())%>
<%
    }
}
%>
 
<%
if (!editable) {
    for (int i=0; i<fvalues.length; i++) {
%>
        <input type="hidden" name="<%=propertyKey%>" value="<%=fvalues[i]%>">
<%
    }
}
%>

Editores para referencias (nuevo en v3.1.3)

Por defecto las referencias se visualizan con una vista de detalle, pero podemos crear nuestro propio editor para las referencias. Por ejemplo, podemos escribir lo siguiente en el archivo editores.xml de nuestra aplicación:
<editor url="colorEditor.jsp">
 <para-referencia modelo="Color"/>
</editor>
 
Con este código estamos diciendo que cualquier referencia a la entidad Color se tiene que visualizar usando colorEditor.jsp (para usar un editor solo para una referencia concreta en una entidad concreta véase la sección Escoger un editor del capítulo sobre Vista).
Aquí tenemos el código para colorEditor.jsp en la carpeta src/main/webapp/xava/editors (web/xava/editors en v6 o anterior) de tu proyecto:
<%@page import="java.util.Iterator"%>
<%@page import="org.openxava.test.model.Color"%>

<%
String propertyKey = request.getParameter("propertyKey"); // Id de la propiedad clave de la referencia (1)
Object value = request.getAttribute(propertyKey + ".value"); // Podemos usar propertyKey + ".value" (2)
if (value == null) value = new Integer(0);
%>

<%
Iterator it = Color.findAll().iterator();
for (int c=0; it.hasNext() && c < 3; c++) {
	Color color = (Color) it.next();
	String checked = value.equals(color.getNumber())?"checked='checked'":"";
%>	
<input name="<%=propertyKey%>" value="<%=color.getNumber()%>" type="radio" <%=checked%> <!-- (3) -->
	tabindex="1"/>
<span>	
	<font color="#<%=color.getHexValue()%>"><b><%=color.getName()%></b></font>
</span>
<%
}
%>
El parámetro "propertyKey" (1) nos da el id de la propiedad clave de la referencia. Podemos usarlo para nombrar el elemento HTML input (3) o para obtener su valor actual (2). La lista de parámetros que se puede usar es:
  1. referenceKey: El identificador único que OX da a esta referencia.
  2. propertyKey: El identificador único de la propiedad que es clave de la referencia.
  3. editable: Si la referencia tiene que ser editable por el usuario.
  4. viewObject: El nombre del objeto de sesión de la subvista que representa esta referencia. Solo aplica a editores compuestos.
  5. propertyPrefix: Prefijo usado para dar nombre a los editores para las propiedades. Solo aplica a editores compuestos.
Además, podemos definir la forma en que se visualizan todas la referencias por defecto para toda nuestra aplicación, usando <para-referencias/>. Para ello hemos de editar nuestro editores.xml y añadir:
<editor nombre="MiReferencia" url="miReferenciaEditor.jsp" enmarcable="true" compuesto="true">
 <para-referencias/>
</editor>
Ya que hemos marcado el editor con <para-referencias/> ahora todas las referencias de nuestra aplicación se visualizarán usando nuestro miReferenciaEditor.jsp. Esta es una forma sencilla de personalizar el comportamiento del generador de interfaz de usuario de OpenXava.

Editores para colecciones (nuevo en v3.1.3)

Por defecto las colecciones se visualizan con una lista de datos tabulares, pero podemos crear nuestro propio editor para colecciones. Por ejemplo, podemos escribir lo siguiente en el archivo editores.xml de nuestra aplicación:
<editor url="comentariosBlogEditor.jsp">
 <para-coleccion modelo="ComentarioBlog"/>
</editor>
Con el código de arriba estamos diciendo que cualquier colección de entidades ComentarioBlog tiene que ser visualizada y editada usando comentariosBlogEditor.jsp (para usar un editor solo para una colección concreta en una entidad concreta ver la sección Escoger un editor en el capítulo sobre Vista).
<para-coleccion /> funciona para colecciones de tipo @OneToMany/@ManyToMany y @ElementCollection.
Aquí tenemos el código para comentariosBlogEditor.jsp:
<jsp:include page="collectionEditor.jsp">
 <jsp:param name="listEditor" value="comentariosBlogListEditor.jsp"/>
</jsp:include>
Esta es una forma habitual de crear un editor para colecciones. Aquí llamamos a collectionEditor.jsp (el editor por defecto de OpenXava para colecciones) enviando como argumento para listEditor un JSP que contiene el editor para parte de la lista. De esta forma tenemos gratis todas las acciones y comportamiento por defecto de las colecciones, por tanto solo hemos de preocuparnos por dibujar la lista.
El comentariosBlogListEditor.jsp en la carpeta src/main/webapp/xava/editors (web/xava/editors en v6 o anterior) de tu proyecto:
<%@ include file="../imports.jsp"%>
 
<%@page import="org.openxava.view.View"%>
<%@page import="org.openxava.model.MapFacade"%>
<%@page import="org.openxava.test.model.Blog"%>
<%@page import="org.openxava.test.model.BlogComment"%>
<%@page import="java.util.Iterator"%>
<%@page import="java.util.Map"%>
<%@page import="java.text.DateFormat"%>
<%@page import="org.openxava.util.Locales"%>
<%@page import="org.openxava.util.Is"%>
 
<jsp:useBean id="context" class="org.openxava.controller.ModuleContext" scope="session"/>
 
<%
String viewObject = request.getParameter("viewObject"); // Id para acceder al objeto view de la colección
View collectionView = (View) context.get(request, viewObject); // Obtenemos el objeto view de la colección mediante context
View rootView = collectionView.getRoot(); // En este caso usamos la vista raiz, la vista de Blog
Map key = rootView.getKeyValues();
if (Is.empty(key)) {
%>
No hay comentarios
<%
} else { // Si la clave tiene valor dibujamos la colección de comentarios
 
Blog blog = (Blog) MapFacade.findEntity("Blog", key);
String action = request.getParameter("rowAction"); // rowAction es la acción para editar o visualizar cada elemento
String actionArgv = ",viewObject=" + viewObject;
%>
 
Estos son los comentarios<br/>
<%
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locales.getCurrent());
int f=0;
for (Iterator it = blog.getComentarios().iterator(); it.hasNext(); f++) {
 ComentarioBlog comentario = (ComentarioBlog) it.next();
%>
<i><b><big>Comentario del <%=df.format(comentario.getFecha())%></big></b></i>
<xava:action action='<%=action%>' argv='<%="row=" + f + actionArgv%>'/>
<p>
<i><%=comentario.getCuerpo()%></i>
</p>
<hr/>
<%
}
 
}
%>
Este editor dibuja los comentarios del blog como un texto simple con una cabecera con la fecha.
La lista de parámetro a usar en un editor de lista para colecciones es:
  1. collectionName: El nombre de la colección tal y como lo tenemos en nuestra entidad.
  2. viewObject: El nombre del objeto de sesión de la subvista que representa esta colección.
  3. rowAction: El nombre calificado de acción (Controlador.accion como está en controladores.xml) a ejecutar en cada elemento para visualizarlo o editarlo.
Por supuesto, podemos crear nuestro editor para colección desde cero, sin usar collectionEditor.jsp. En este caso has de escribir la interfaz de usuario completa para la colección. Veamos un ejemplo en nombresTransportistaEditor.jsp:
<%@page import="org.openxava.view.View"%>
<%@page import="org.openxava.model.MapFacade"%>
<%@page import="org.openxava.test.model.Carrier"%>
<%@page import="java.util.Iterator"%>
 
<jsp:useBean id="context" class="org.openxava.controller.ModuleContext" scope="session"/>
 
<%
String viewObject = request.getParameter("viewObject"); // viewObject es el id del objeto view del padre
View view = (View) context.get(request, viewObject); // view es el objeto view de Transportista, el padre de la colección
Transportista transportista = (Transportista) MapFacade.findEntity("Transportista", view.getKeyValues());
%>
Los compañeros de <%=transportista.getNombre()%> son:<br>
<ul>
<%
for (Iterator it = transportista.getCompaneros().iterator(); it.hasNext(); ) {
 Transportista companero = (Transportista) it.next();
%>
<li><%=companero.getNombre()%></li>
<%
}
%>
</ul>
En este caso escribimos el código para dibujar la colección completamente, si queremos tener algunas acciones para trabajar con la colección tenemos que ponerlas nosotros mismos. ¡Ojo!, porque aquí viewObject es la vista del objeto que contiene la colección, no de la colección en sí.
La lista de parámetros a usar en un editor para colecciones es:
  1. collectionName: El nombre de la colección tal y como lo tenemos en nuestra entidad..
  2. viewObject: El nombre del objeto de sesión para la vista o subvista que representa el objeto padre de esta colección

Además, podemos definir la forma en que visualizan todas la colecciones en toda nuestra aplicación, usando <para-colecciones/> para colecciones @OneToMany/@ManyToMany y <para-colecciones-elementos /> (nuevo en v5.0) para @ElementCollection. Editemos nuestro editors.xml y añadamos:
<editor nombre="MiColeccion" url="miColeccionEditor.jsp">
 <para-colecciones/>
</editor>
 
<editor nombre="MiColeccionElementos" url="miColeccionElementosEditor.jsp">
 <para-colecciones-elementos/> <!-- Nuevo en v5.0 -->
</editor>
Ahora todas las colecciones @OneToMany/@ManyToMany en nuestra aplicación se visualizan usando nuestro miColeccionEditor.jsp y las @ElementCollection usando nuestro miColeccionElementosEditor.jsp.

Editores para tabs (modo lista) (nuevo en v4.6)

Por defecto los datos tabulares (los que se muestran en modo lista) se visualizan con una lista, pero podemos crear nuestro propio editor. Por ejemplo, podemos escribir esto en el editores.xml de nuestra aplicación:
<editor url="empleadoCorporativoListEditor.jsp">
  <para-tab modelo="EmpleadoCorporativo"/>
</editor>
Con el código de arriba estamos diciendo que todos los tabs (es decir todas la listas) para la entidad EmpleadoCorporativo tienen que ser editados y visualizados usando empleadoCorporativoListEditor.jsp (para usar un editor sólo para un tab concreto de una entidad ver la sección Escogiendo un editor).
Aqui tenemos el código para empleadoCorporativoListEditor.jsp en la carpeta src/main/webapp/xava/editors (web/xava/editors en v6 o anterior) de tu proyecto:
<%@ include file="../imports.jsp"%>
 
<jsp:useBean id="context" class="org.openxava.controller.ModuleContext" scope="session"/>
 
<%
String tabObject = request.getParameter("tabObject");
tabObject = (tabObject == null || tabObject.equals(""))?"xava_tab":tabObject;
org.openxava.tab.Tab tab = (org.openxava.tab.Tab) context.get(request, tabObject);
String condition = tab.getBaseCondition()==null?"":tab.getBaseCondition();
String all = condition.equals("")?"selected":"";
String low = condition.contains("<=")?"selected":"";
String high = condition.contains(">")?"selected":"";
String action="openxava.executeAction('OpenXavaTest', 'EmpleadoCorporativo'," +
    "false, false, 'EmpleadoCorporativo.filtrar', 'segmento='+this.value)";
%>
 
<select name="<xava:id name='escogerSegmento'/>" onchange=
    "<%=action%>">
    <option value="all" <%=todos%>>Todos los empleados</option>
    <option value="low" <%=bajo%>>Empleados con salario bajo</option>
    <option value="high" <%=alto%>>Empleados con salario alto</option>
</select>
 
<jsp:include page="listEditor.jsp"/>
Un detalle importante es que este editor incluye listEditor.jsp al final. listEditor.jsp es el editor por defecto para modo lista, por tanto en este caso simplemente estamos refinando la lista estándar añadiendo un combo para escoger un filtro personalizado. Sin embargo, podemos crear nuestro propio editor para lista desde cero, por ejemplo, el siguiente editor, fichasClienteListEditor.jsp, muestra la lista de clientes como una fila de fichas:
<%@ include file="../imports.jsp"%>
 
<jsp:useBean id="context" class="org.openxava.controller.ModuleContext" scope="session"/>
 
<%
String collection = request.getParameter("collection");
String id = "list";
String collectionArgv = "";
String prefix = "";
String tabObject = request.getParameter("tabObject");
tabObject = (tabObject == null || tabObject.equals(""))?"xava_tab":tabObject;
if (collection != null && !collection.equals("")) {
    id = collection;
    collectionArgv=",collection="+collection;
    prefix = tabObject + "_";
}
org.openxava.tab.Tab tab = (org.openxava.tab.Tab) context.get(request, tabObject);
org.openxava.tab.impl.IXTableModel model = tab.getTableModel();
for (int r=tab.getInitialIndex(); r<model.getRowCount() && r < tab.getFinalIndex(); r++) {
%>
    <xava:link action="List.viewDetail"><div class="ficha-cliente">
    <h4><%=model.getValueAt(r, 1)%>(<%=model.getValueAt(r, 0)%>)</h4>
    <%=model.getValueAt(r, 2)%><br/>
    <%=model.getValueAt(r, 3)%> (<%=model.getValueAt(r, 4)%>)
    </div></xava:link>
<%
}
%>
Para este editor usamos una clase CSS, ficha-cliente (el estilo en línea no está permitido desde v7.1), pon esta clase CSS en un archivo fichasClienteListEditor.css dentro de la carpeta src/main/webapp/xava/editors/style (web/xava/editors/style en v6 o anterior) de tu proyecto, puede que necesites crear la carpeta style la primera vez:
.ficha-cliente {
    border: 2px solid rgb(130, 143, 149); 
    display: inline-block; 
    padding: 10px; 
    margin-bottom: 10px;
}

Además, podemos definir la forma en que las listas se visualizan por defecto en toda la aplicación, usando <para-tabs/>, para ello editamos editores.xml y añadimos:
<editor nombre="MiLista" url="miListaEditor.jsp">
  <para-tabs/>
</editor>
Como hemos marcado el editor con <for-tabs/> ahora todos los tabs de nuestra aplicación se visualizaran usando nuestro miListaEditor.jsp. Esta es una forma sencilla de personalizar el comportamiento del generador de interfaz gráfica de OpenXava.

Editores para formatos de lista (nuevo en v5.7)

Todos los editores marcados con <for-tabs/> en default-editors.xml y <para-tabs/> en editores.xml se usan como formatos de lista diferentes que el usuario puede escoger. Por ejemplo, si tenemos esto en openxava/src/main/resources/xava/default-editors.xml (OpenXava/xava/default-editors.xml antes de v7):
<editor name="List" url="listEditor.jsp" icon="table-large">
    <for-tabs/>
</editor>
 
<editor name="Charts" url="chartsEditor.jsp"
    selectable-items="false"
    icon="chart-line"
    init-action="Chart.init"
    release-action="Chart.release">
    <for-tabs/>
</editor>
Y esto en editores.xml de tu proyecto:
<editor nombre="MiFicha" url="miFichaEditor.jsp" icono="view-module">
    <para-tabs/>
</editor>
Tu usuario tendrá tres formatos para escoger en la lista:
tab050.png
Es decir, a partir de v5.7 <para-tabs/> no sustituye sino acumula. Fíjate en el atributo icono en <editor/>, usado como icono para el botón de formato.
Si quieres restringir los formatos disponibles sin tener que tocar openxava/src/main/resources/xava/default-editors.xml (OpenXava/xava/default-editors.xml antes de v7) usa valores-defecto-tabs.xml de tu proyecto.
Lo explicado aquí es para hacer cambios a nivel global, para cambiar los formatos para una lista concreta puedes usar el atributo editors de la anotación @Tab en tu entidad.

Editores para formatos de lista en entidades específicas (nuevo en v7.3)

A partir de v7.3, en los editores marcados con <for-tabs/> y <para-tabs/>, se podrán agregar condiciones:
<editor nombre="MiEditor" url="miEditor.jsp"
    icono="puzzle">
    <para-tabs> 
<tiene-tipo tipo="java.util.Date">
<tiene-tipo tipo="java.time.LocalDate">
<tiene-anotacion anotacion="DateTime">
<tiene-estereotipo estereotipo="FECHAHORA">
</para-tabs>
</editor>
Las condiciones te permiten mostrar el editor para formatos de lista en los módulos cuya entidades cumplan con alguna de las condiciones definidas.
En <tiene-tipo>, la condición se cumple si la entidad contiene alguna propiedad del tipo definido. Recuerda que debes incluir también el nombre del paquete. En el ejemplo anterior, la entidad debe tener una propiedad de tipo Date (java.util.Date) o LocalDate (java.time.LocalDate).
En <tiene-anotacion>, la condición se cumple si en la entidad posee alguna propiedad que tenga la anotación definida. En el ejemplo anterior, la entidad debe tener una propiedad con la anotación @DateTime.
En <tiene-estereotipo>, la condición se cumple si en la entidad existe alguna propiedad que lleve el estereotipo definido. En el ejemplo anterior, la entidad debe tener una propiedad con @Stereotype("FECHAHORA").

De esta manera, puedes evitar que ciertos formatos de lista aparezcan en determinados módulos. Por ejemplo, no sería útil permitir la navegación a un formato de lista similar a Calendario en un módulo donde no existan fechas.

Editores para anotaciones (nuevo en v6.6)

Es posible asociar un editor a una anotación Java y así cuando una propiedad se anote con esa anotación se usará el editor correspondiente. Por ejemplo, puedes definir una anotación como esta:
package com.tuempresa.facturacion.anotaciones;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface Colorido {

    String color() default "black";

}
Fíjate como es una anotación Java convencional, sin ningún requisito especial. Puedes incluso usar anotaciones ya existentes de cualquier librería Java.
Ahora puedes anotar una propiedad de tu entidad con tu anotación, de esta forma:
@Column(length=40) @Required
@Colorido(color = "green") 
String nombre;
Lo que queremos es que la propiedad nombre se visualice usando tu propio editor en lugar del editor por defecto para propiedades String. Para ello, define tu propio editor en editores.xml y asígnale tu anotación usando para-anotacion:
<editor nombre="Colorido" url="coloridoEditor.jsp">
    <propiedad nombre="fondo" valor="yellow"/> 
    <para-anotacion anotacion="com.tuempresa.facturacion.anotaciones.Colorido"/>
</editor>
Aquí estás asociando la anotación Colorido al editor coloridoEditor.jsp. También definimos la propiedad "fondo" para enviar al editor. Este es el código de coloridoEditor.jsp en la carpeta src/main/webapp/xava/editors (web/xava/editors en v6 o anterior) de tu proyecto:
<%
String fondo = request.getParameter("fondo");
String color = request.getParameter("color");
%>

<span class="colorido-color-<%=color%> colorido-fondo-<%=background%>">
	<jsp:include page="textEditor.jsp"/>
</span>
En este caso el editor simplemente envuelve el textEditor.jsp estándar para definir colores personalizados para las letras y el fondo. Lo importante aquí es que puedes leer el atributo definido en tu anotación (color = "green" en este caso) usando request.getParameter("color").
Para este editor usamos algunas clases CSS para los colores (porque los estilos en línea no se permiten desde la v7.1), pon estas clases CSS en un archivo coloridoEditor.css dentro de la carpeta src/main/webapp/xava/editors/style (web/xava/editors/style en v6 o anterior) de tu proyecto, puede que necesites crear la carpeta style la primera vez:
.colorido-color-black input { color: black; }
.colorido-fondo-black input { background: black; }
.colorido-color-white input{ color: white; }
.colorido-fondo-white input{ background: white; }
.colorido-color-red input{ color: red; }
.colorido-fondo-red input{ background: red; }
.colorido-color-green input{ color: green; }
.colorido-fondo-green input{ background: green; }
.colorido-color-blue input{ color: blue; }
.colorido-fondo-blue input{ background: blue; }
.colorido-color-yellow input{ color: yellow; }
.colorido-fondo-yellow input{ background: yellow; }
.colorido-color-orange input{ color: orange; }
.colorido-fondo-orange input{ background: orange; }
.colorido-color-purple input{ color: purple; }
.colorido-fondo-purple input{ background: purple; }
.colorido-color-gray input{ color: gray; }
.colorido-fondo-gray input{ background: gray; }

JavaScript en los editores

A partir de v4m3

Si necesitas usar funciones JavaScript, ya sean propias o de terceros, en tu editor, no lo puedes hacer incluyendolas directamente en el JSP, porque el código HTML del editor se carga vía AJAX. En lugar de eso, has de poner tus funciones en un archivo JS en la carpeta src/main/webapp/xava/editors/js de tu proyecto (web/xava/editors/js en v6 o anteriores). Si la carpeta todavía no existe, creala. Todo el JavaScript que hay ahí se carga automáticamente.
Además, desde v7.1 no se permiten los eventos en línea como onclick, es decir, el siguiente código no está permitido:
<input ... onclick="f()"/> <!-- NO PERMITIDO DESDE V7.1-->
En su lugar has de asociar los eventos desde el código en tus archivos JS. Para tu código JavaScript crea un archivo llamado miEditor.js (o cualquier otro nombre que quieras), y ponlo en la carpeta src/main/webapp/xava/editors/js (web/xava/editors/js en v6 o anteriores).
La mayoría de la veces necesitarás lógica JavaScript para inicializar tu editor, no puedes usar el evento onload o equivalente, porque el código HTML del editor es cargado vía AJAX, por tanto no se produce carga de la página. Has de registrar tu código de inicialización en OpenXava. Puedes hacerlo en tu archivo miEditor.js (o cualquier otro archivo en src/main/webapp/xava/editors/js), como sigue:
openxava.addEditorInitFunction(function() {
 /*
 Aquí tu código de inicialización para tu editor.
 Es decir, las cosas que normalmente pondrías en el event onload de JavaScript
 o $(function() { ... }) de jQuery
 */
 ...
});
Vemos como usamos openxava.addEditorInitFunction() para registrar una función de inicialización. El evento JavaScript onload o el evento ready() de jQuery no funciona, porque no se produce carga de página, en vez de eso el editor se genera en el servidor, se carga vía AJAX y se inserta en la página que ya se estaba visualizando.
A partir de v4.8.1 puedes definir una función de destrucción para tu editor en tu miEditor.js:
openxava.addEditorDestroyFunction(function() { // Nuevo en v4.8.1
/*
Aquí el código de destrucción de tu editor.
Esto es para liberar los recursos obtenidos por el editor.
*/
...
});

A partir de v7.1 puedes definir una función a ejecutar antes de cada llamada AJAX de OpenXava, ponla en tu miEditor.js:

openxava.addEditorPreRequestFunction(function() { // Nuevo en v7.1
/*
Aquí el código a ejecutar para tu editor
antes de cada llamada AJAX de OpenXava.
*/
...
});

Por ejemplo, si quieres mostrar un diálogo de JavaScript con un mensaje cuando el usuario pulse en un botón de tu editor, y tienes este código en tu miEditor.jsp:

<input class="mi-editor" type="button" value="Di hola"/>
Simplemente añade el siguiente código en tu miEditor.js:
openxava.addEditorInitFunction(function() {
	
	$(".mi-editor").click(function() {
  		alert("Hola");
	});
	
});
En este caso usamos jquery para asociar el evento, pero puedes hacerlo de cualquier otra forma.

La función eval() en JavaScript no está permitida en el código desde la versión 7.3. Sin embargo, es posible sortear esta limitación agregando unsafeEvalInScripts=true en el archivo xava.properties.

Hasta v4m2

Has de poner todo el código JavaScript para todos tus editores en custom-editors.js en la carpeta web/xava/js. Esta técnica todavía se soporta, aunque se considera obsoleta.

Until 3.0.x

No se usa AJAX, por tanto el código JavaScript se puede incluir directamente en el JSP del editor.

CSS en editores (nuevo en v5.4)

Todos los archivos CSS en la carpeta src/main/webapp/xava/editors/style (web/xava/editors/style en v6 o anteriores) de nuestra aplicación se cargan automáticamente. Si la carpeta todavía no existe, creala. Aquí se ponen los archivos CSS necesarios por los componentes JavaScript que usamos en nuestros editores. También, podemos poner los CSS específicos de nuestros editores. No hay que poner en src/main/webapp/xava/editors/style los CSS para el estilo general de la aplicación.

Editores personalizables y estereotipos para crear combos

Podemos hacer que propiedades simples que se visualicen como combos que rellenen sus datos desde la base datos. Veámoslo.
Definimos las propiedades así en nuestro componente:
@Stereotype("FAMILY")
private int familyNumber;
 
@Stereotype("SUBFAMILY")
private int subfamilyNumber;
Y en nuestro editores.xml ponemos:
<editor url="descriptionsEditor.jsp"> <!-- 10 -->
 <propiedad nombre="modelo" valor="Familia"/> <!-- 1 -->
 <propiedad nombre="propiedadClave" valor="codigo"/> <!-- 2 -->
 <propiedad nombre="propiedadDescripcion" valor="descripcion"/> <!-- 3 -->
 <propiedad nombre="ordenadoPorClave" valor="true"/> <!-- 4 -->
 <propiedad nombre="readOnlyAsLabel" valor="true"/> <!-- 5 -->
 <para-estereotipo estereotipo="FAMILIA"/> <!-- 11 -->
</editor>
 
<!-- Es posible especificar dependencias de estereotipos o propiedades -->
<editor url="descriptionsEditor.jsp" <!-- 10 -->
 depende-de-estereotipos="FAMILIA"> <!-- 12 -->
<!--
<editor url="descriptionsEditor.jsp" depende-de-propiedades="codigoFamilia"> <!-- 13 -->
-->
 <propiedad nombre="modelo" valor="Subfamilia"/> <!-- 1 -->
 <propiedad nombre="propiedadClave" valor="codigo"/> <!-- 2 -->
 <propiedad nombre="propiedadesDescripcion" valor="codigo, descripcion"/> <!-- 3 -->
 <propiedad nombre="condicion" value="${codigoFamilia} = ?"/> <!-- 6 -->
 <propiedad nombre="estereotiposValoresParametros" valor="FAMILIA"/> <!-- 7 -->
 <!--
 <propiedad nombre="propiedadesValoresParametros" valor="codigoFamilia"/> <!-- 8 -->
 -->
 <propiedad nombre="formateadorDescripciones" <!-- 9 -->
 valor="org.openxava.test.formatters.FormateadorDescripcionesFamilia"/>
 <para-estereotipo estereotipo="SUBFAMILIA"/> <!-- 11 -->
</editor>
Al visualizar una vista con estas dos propiedades codigoFamilia y codigoSubfamilia sacará un combo para cada una de ellas, el de familias con todas las familias disponible y el de subfamilias estará vacío y al escoger una familia se rellenará con sus subfamilias correspondientes.
Para hacer eso asignamos a los estereotipos (FAMILIA y SUBFAMILIA en este caso(11)) el editor descriptionsEditor.jsp (10) y lo configuramos asignandole valores a sus propiedades. Algunas propiedades con las que podemos configurar estos editores son:
  1. modelo: Modelo del que se obtiene los datos. Puede ser el nombre de una entidad (Factura) o el nombre de un modelo usado en una colección incrustada (Factura.LineaFactura).
  2. propiedadClave o propiedadesClave: Propiedad clave o lista de propiedades clave que es lo que se va a usar para asignar valor a la propiedad actual. No es obligado que sean las propiedades clave del modelo, aunque sí que suele ser así.
  3. propiedadDescripcion o propiedadesDescripcion: Propiedad o lista de propiedades a visualizar en el combo.
  4. ordenadoPorClave: Si ha de estar ordenador por clave, por defecto sale ordenado por descripción. También se puede usar order con un orden al estilo SQL, si lo necesitas.
  5. readOnlyAsLabel: Si cuando es de solo lectura se ha de visualizar como una etiqueta. Por defecto es false.
  6. condicion: Condición para restringir los datos a obtener. Tiene formato SQL, pero podemos poner nombres de propiedades con ${}, incluso calificadas. Podemos poner argumentos con ?. En ese caso es cuando dependemos de otras propiedades y solo se obtienen los datos cuando estas propiedades cambian.
  7. estereotiposValoresParametros: Lista de estereotipos de cuyas propiedades dependemos. Sirven para rellenar los argumentos de la condición y deben coincidir con el atributo depende-de-estereotipos. (12)
  8. propiedadesValoresParametros: Lista de propiedades de las que dependemos. Sirven para rellenar los argumentos de la condición y deben coincidir con el atributo depende-de-propiedades. (13)
  9. formateadorDescripciones: Formateador para las descripciones visualizadas en el combo. Ha de implementar IFormatter.
Siguiendo este ejemplo podemos hacer fácilmente nuestro propios estereotipos que visualicen una propiedad simple con un combo con datos dinámicos. Sin embargo, en la mayoría de los casos es más conveniente usar referencias visualizadas como @DescriptionsList; pero siempre tenemos la opción de los estereotipos disponible.

Vistas JSP propias y taglibs de OpenXava

Obviamente la mejor forma de crear interfaces de usuario es usando las anotaciones de vista que se ven en el capítulo sobre Vista. Pero, en casos extremos quizás necesitemos definir nuestra propia vista usando JSP. OpenXava nos permite hacerlo. Y para hacer más fácil la labor podemos usar algunas taglibs JSP provistas por OpenXava. Veamos un ejemplo.

Ejemplo

Lo primero es indicar en nuestro módulo que queremos usar nuestro propio JSP, en aplicacion.xml:
<modulo nombre="ComercialJSP" carpeta="facturacion.variaciones">
 <modelo nombre="Comercial"/>
 <vista nombre="ParaJSPPropio"/> <!-- 1 -->
 <vista-web url="jsp-propios/comercial.jsp"/> <!-- 2 -->
 <controlador nombre="Typical"/>
</modulo>
Si usamos vista-web (2) al definir el módulo, OpenXava usa nuestro JSP para dibujar el detalle, en vez de usar la vista generada automáticamente. Opcionalmente podemos definir una vista OpenXava con vista (1), esta vista es usada para saber que eventos lanzar y que propiedades llenar, si no se especifica se usa la vista por defecto de la entidad; aunque es aconsejable crear una vista OpenXava explícita para nuestra vista JSP, de esta manera podemos controlar los eventos, las propiedades a rellenar, el orden del foco, etc explicitamente. Podemos poner nuestro JSP dentro de la carpeta src/main/webapp/custom-jsp/jsp-propios (u otra de nuestra elección) de nuestro proyecto (web en lugar de src/main/webapp para versiones anteriores a v7.0), y este JSP puede ser así:
<%@ include file="../xava/imports.jsp"%>
 
<table>
<tr>
 <td>C&oacute;digo: </td>
 <td>
 <xava:editor property="codigo"/>
 </td>
</tr>
<tr>
 <td>Nombre: </td>
 <td>
 <xava:editor property="nombre"/>
 </td>
</tr>
 
<tr>
 <td>Nivel: </td>
 <td>
 <xava:editor property="nivel.id"/>
 <xava:editor property="nivel.descripcion"/>
 </td>
</tr>
</table>
Somos libres de crear el archivo JSP como queramos, pero puede ser práctico usar las taglibs de OpenXava, en este caso, por ejemplo, se usa <xava:editor/>, esto dibuja un editor apto para la propiedad indicada, además añade el JavaScript necesario para lanzar los eventos. Si usamos <xava:editor/>, podemos manejar la información visualizada usando el objeto xava_view (del tipo org.openxava.view.View), por lo tanto todos los controladores estándar de OpenXava (CRUD incluido) funcionan.
Podemos observar como las propiedades cualificadas están soportadas (como nivel.id o nivel.descripcion) (nuevo en v2.0.1), además cuando el usuario rellena nivel.id, nivel.descripcion se llena con su valor correspondiente. Sí, todo el comportamiento de una vista OpenXava está disponible dentro de nuestros JSPs si usamos las taglibs de OpenXava.
Veamos las taglib de OpenXava.

xava:editor

La marca (tag) <xava:editor/> permite visualizar un editor (un control HTML) para nuestra propiedad, de la misma forma que lo hace OpenXava cuando genera automáticamente la interfaz de usuario.
<xava:editor
 property="nombrePropiedad" <!-- 1 -->
 editable="true|false" <!-- 2 Nuevo en v2.0.1 -->
 throwPropertyChanged="true|false" <!-- 3 Nuevo en v2.0.1 -->
/>
  1. property (obligado): Propiedad del modelo asociado al módulo actual.
  2. editable (opcional): Nuevo en v2.0.1. Fuerza a este editor a ser editable, de otra forma se asume un valor por defecto apropiado.
  3. throwPropertyChanged (opcional): Nuevo en v2.0.1. Fuerza a este editor a lanzar el evento de propiedad cambiada, de otra forma se asume un valor por defecto apropiado.
Esta marca genera el JavaScript para permitir a nuestra vista trabajar de la misma forma que una vista automática. Las propiedades calificadas (propiedades de referencias) están soportadas (nuevo en v2.0.1).

xava:action, xava:link, xava:image, xava:button

La marca (tag) <xava:action/> permite dibujar una acción (un botón o una imagen que el usuario puede pulsar).
<xava:action action="controlador.accion" argv="argv"/>
El atributo action indica la acción a ejecutar, y el atributo argv (opcional) nos permite establecer valores a algunas propiedades de la acción antes de ejecutarla. Un ejemplo:
<xava:action action="CRUD.save" argv="resetAfter=true"/>
Cuando el usuario pulse en la acción se ejecutará CRUD.save, antes pone a true la propiedad resetAfter de la acción.
La acción se visualiza como una imagen si tiene una imagen asociada y como un botón si no tiene imagen asociada. Si queremos detereminar el estilo de visualización podemos usar directamente las siguientes marcas: <xava:button/>, <xava:image/> o <xava:link/> similares a <xava:action/>.
Podemos especificar una cadena vacía para la acción (nuevo en v2.2.1), como sigue:
<xava:action action=""/>
En este caso la marca (tag) no tiene efecto y no se produce error. Esta característica puede ser útil cuando el nombre de la acción lo obtenemos dinámicamente (es decir action=”<%=micodigo()%>”), y el valor pueda estar vacío en ciertos casos.

xava:message (nuevo en v2.0.3)

La marca (tag) <xava:message/> permite mostrar en HTML un mensaje de los archivos de recursos i18n de OpenXava.
<xava:message key="clave_mensaje" param="parametroMensaje" intParam="paramMensaje"/>
El mensaje es buscado primero en los archivos de recursos de nuestro proyecto (miproyecto/src/main/resources/i18n/miproyecto-messages_es.properties para v7 o superior, y MiProyecto/i18n/MensajesMiProyecto.properties para v6 o anterior) y si no se encuentra ahí es buscado en los mensajes por defecto de OpenXava (openxava/src/main/resources/i18n/Messages_en.properties para v7 o superior, y OpenXava/i18n/Messages.properties para v6 o anterior).
Los atributos param y intParam son opcionales. El atributo intParam es usado cuando el valor a enviar como parametro es de tipo int. Si usamos Java 5 podemos usar siempre param porque int es automáticamente convertido por autoboxing. A partir de v5.9 también se puede usar param1, param2, param3 y param4.
Esta marca solo genera el texto del mensaje, sin ningún tipo de formateo HTML.
Un ejemplo:
<xava:message key="cantidad_lista" intParam="<%=cantidadTotal%>"/>

xava:label (nuevo en v5.5)

La marca <xava:label/> permite mostrar en HTML una etiqueta de los archivos de etiquetas de OpenXava.
<xava:label key="nombreMiembro"/>
El mensaje es buscado primero en los archivos de etiquetas de nuestro proyecto (miproyecto/src/main/resources/i18n/miproyecto-labels_es.properties para v7 o superior, y MiProyecto/i18n/EtiquetasMiProyecto.properties para v6 o anterior) y si no se encuentra ahí es buscado en los mensajes por defecto de OpenXava (openxava/src/main/resources/i18n/Labels_en.properties para v7 o superior, y OpenXava/i18n/Labels.properties para v6 o anterior).
Esta marca solo genera el texto de la etiqueta, sin ningún tipo de formateo HTML.
Con <xava:label/> en lugar de escribir:
<tr>
    <td>Number: </td><td>
    <xava:editor property="number"/>
    </td>
</tr>
Puedes escribir esto:
<tr>
    <td><xava:label key="number"/>: </td><td>
    <xava:editor property="number"/>
    </td>
</tr>
Y así tener la etiqueta traducida.

xava:descriptionsList (nuevo en v2.0.3)

La marca (tab) <xava:descriptionsList/> permite visualizar una lista descripciones (un combo HTML) para una referencia, del mismo modo que lo hace OpenXava cuando genera la interfaz de usuario automáticamente.
<xava:descriptionsList
 reference="nombreReferencia"  <!-- 1 -->
readOnlyAsLabel="true|false" <!-- 2 Nuevo en v6.0.1 -->
/>
  1. reference (obligado): Una referencia del modelo asociado con el módulo actual.
  2. readOnlyAsLabel (opcional): Nuevo en v6.0.1. Si es true se visualizará como una etiqueta cuando la referencia sea de sólo lectura.
Esta marca genera el JavaScript necesario para permitir a la vista personalizada trabajar de la misma forma que una automática.
Un ejemplo:
<tr>
 <td>Nivel: </td>
 <td>
 <xava:descriptionsList reference="nivel"/>
 </td>
</tr>
En este caso nivel es una referencia al modelo actual (por ejemplo Comercial). Un combo es mostrado con todos los niveles disponibles.

Modificar el código JSP del núcleo de OpenXava

Estas instrucciones son para v7 o superior, con v6 o anterior tienes el código JSP dentro de la carpeta web de tu aplicación
OpenXava utiliza un grupo de JSPs como parte de su motor para generar la interfaz de usuario. Puedes modificar cualquiera de estos JSP solo para tu aplicación y así personalizar el funcionamiento de OpenXava. Sin embargo, desaconsejamos modificar las JSP de OpenXava (a excepción de welcome.jsp y firstSteps.jsp), porque aunque te da mucha flexibilidad tendrás problemas al actualizar a una nueva versión de OpenXava. La mayoría de las veces, tiene otras opciones para modificar la forma en que se genera la interfaz de usuario, como:
De todos modos, si decides modificar las JSP de OpenXava. Esta es la forma. Primero mira los JSPs disponibles en código OpenXava en GitHub, aquí:
https://github.com/openxava/openxava/tree/7.1.1/openxava/src/main/resources/META-INF/resources (cambia 7.1.1 por la versión de OpenXava que estés usando)
Ahí tienes dos carpetas, naviox y xava. La carpeta naviox genera el marco de navegación e inicio de sesión, mientras que la carpeta xava genera la interfaz de usuario para el módulo, incluido el modo de detalle y lista. Debes copiar el JSP que deseas modificar de GitHub a la carpeta src/main/webapp en tu proyecto. Por ejemplo, supongamos que quieres modificar la forma en que funciona la barra de botones. Has de descargar el código de la barra de botones JSP desde aquí:
https://github.com/openxava/openxava/blob/7.1.1/openxava/src/main/resources/META-INF/resources/xava/buttonBar.jsp (cambia 7.1.1 por la versión de OpenXava que estés usando)
Pulsa en el botón Raw. Luego copia buttonBar.jsp en la carpeta src/main/webapp/xava de tu proyecto y ahora ya puedes modificar el buttonBar.jsp que tienes. Tu proyecto usará tu propio buttonBar.jsp en lugar del incluido en el jar de OpenXava. Ten en cuenta que en futuras versiones de OpenXava buttonBar.jsp podría modificarse, quizás para corregir un error, por lo tanto, después de actualizar a una nueva versión, debes comparar el nuevo código de buttonBar.jsp con el antiguo código de buttonBar.jsp para ver si hay cambios, y si es el caso, tienes que aplicar esos cambios a tu propio buttonBar.jsp.
Generalmente no necesitas modificar ninguna JSP de OpenXava, pero tenemos dos excepciones, la página de Bienvenida, naviox/welcome.jsp (a partir de v7.3 está incluida en los nuevos proyectos para no tener que copiarla desde el GitHub), y la página de Primeros Pasos, naviox/firstSteps.jsp (aunque es preferible usar initialModule en naviox.properties como se explica aquí). La página welcome.jsp es la página a la que va el usuario cuando entra en la raíz de tu aplicación, mientras que firstSteps.jsp es la página a la que va después de iniciar sesión en la aplicación por primera vez.
Para usar JavaScript en las páginas del núcleo de OpenXava, coloca el JavaScript en archivos JS externos e inclúyelos en tus JSPs. No se recomienda usar JavaScript en línea porque en muchas páginas, como las que obtienen su contenido a través de AJAX, no va a funcionar. En otras páginas, como welcome.jsp, encabezados, pie de página, etc., podría funcionar, pero desde la versión 7.1 debes agregar el atributo nonce usando <xava:nonce />, de esta manera:
<%@include file="../xava/imports.jsp"%>
    
    ...
    
<script type="text/javascript" <xava:nonce/>> 
    var button = document.getElementById('welcome_go_signin');
    button.onclick = function () { window.location='m/SignIn'; }
</script>
Fíjate en el nuevo elemento <xava:once> y que has de incluir imports.jsp.

Configuración de propiedades en xava.properties

El archivo xava.properties permite cambiar el comportamiento de OpenXava para toda la aplicación.

Propiedad
Descripción
Valor por defecto
Correo Electronico
emailAsUserNameInPortal (quitado a partir de v7.0)
false
smtpHost
Servidor de correo SMTP

smtpHostTrusted (nuevo en v4.7)
Si es true se puede utilizar un servidor de correos SMTP con el certificado vencido
false
smtpPort
Puerto para envio de correos

smtpUserId
Usuario para conectar al servidor SMTP

smtpUserPassword
Contraseña del usuario para servicios de correo

smtpStartTLSEnable (nuevo en v5.6)
Si es true activa el uso de la orden STARTTLS (si lo soporta el servidor) para cambiar la conexión a una conexión protegida con TLS antes de usar cualquier orden de identificación.
false
smtpFromEmail (nuevo en v6.2)
Valor para el campo from del mensaje. Úsalo si necesitas un valor diferente para el id de usuario y para el campo from (útil en entornos del tipo AWS SES).
El valor de smtpUserId

Persistencia
defaultPersistenceUnit
Unidad de persistencia predeterminada
default
jpaCodeInPOJOs (quitado a partir de v5.6)

Depends on persistence provider
mapFacadeAsEJB

false
mapFacadeAutoCommit

false
persistenceProviderClass (quitado a partir de v5.6)
Clase encargada de manejar la persistencia de datos
org.openxava.model.impl.JPAPersistenceProvider

Etiquetas, Mensajes y Localización
i18nWarnings

false
portletLocales (quitado a partir de v7.0) Si no se especifica se usan los locales incluidos en la carpeta i18n
bg, ca, de, en, es, fr, in, it, ja, ko, nl, pl, pt, ru, sv, zh

Aplicación y Controladores
defaultLabelFormat
Possibles values for defaultLabelFormat are: NORMAL, SMALL and NO_LABEL
NORMAL
defaultLabelStyle
Se han definido: bold-label, italic-label, además de que puede definir sus propios estilos

defaultModeController (nuevo en v4m5)
Los valores posibles para defaultModeController son: Mode, DetailList, DetailOnly, ListOnly and SplitOnly
Mode
duplicateComponentWarnings
Cuando se encuentran componentes con nombres duplicados se generan mensajes de advertencia
true
failOnAnnotationMisuse
Lanza un error si algún miembro (propiedades, referencias o colecciones) tienen anotaciones que no les son aplicables
true
generateDefaultModules
Si es true no es requerido definir los módulos en application.xml / applicacion.xml. OX se encarga de generarlos automaticamente
true

Estilos
liferay6StyleClass (nuevo en v4m6, quitado a partir de v7.0)
Estilo compatible con liferay 6
org.openxava.web.style.Liferay6Style
liferay51StyleClass (quitado a partir de v7.0) Estilo compatible con liferay 5.1
org.openxava.web.style.Liferay51Style
liferay41StyleClass (quitado a partir de v7.0) Estilo compatible con liferay 4.1
org.openxava.web.style.Liferay41Style
liferay43StyleClass (quitado a partir de v7.0) Estilo compatible con liferay 4.3
org.openxava.web.style.Liferay43Style
webSpherePortal61StyleClass (quitado a partir de v7.0) Estilo compatible WebSphere Portal 6.1
org.openxava.web.style.WebSpherePortal61Style
styleClass
Maneja la asignación de atributos class para los elementos desplegables.
org.openxava.web.style.XavaStyle (desde v6.0)
org.openxava.web.style.Liferay51Style (hasta v5.9.1)
styleCSS
URL del archivo CSS que provee las caracteristicas de la interfase visual.
terra.css (desde v6.0)
liferay51/css/everything_unpacked.css (hasta v5.9.1)
themes (nuevo en v6.3)
Lista de archivos CSS separados por coma de los estilos disponibles para ser elegidos como temas por el usuario. Si el valor está vacío el selector de temas no está disponible para el usuario.
Vacío

Vistas
alignedByColumns (nuevo en v4.7.1)
Si es true las propiedades de la vista son desplegadas alineadas por columnas. Sólo funciona en las implementaciones por defecto de layoutParser & layoutPainter. Provoca que las todas las vistas se comporten como si tuviesen # al inicio
false
buttonsForNoImageActions
Si es true, cuando una acción no tiene imagen asociada muestra un botón. Si es false entonces muestra un hipervínculo
false
layoutParser (nuevo en v4.5, hasta v6.0.2)
Nombre del interpretador de despliegue de vistas. Ha de implementar
org.openxava.web.layout.ILayoutParser
Hasta v5.4.1: org.openxava.web.layout.impl.DefaultLayoutParser
A partir de v5.5: null (por tanto usa JSP)
layoutPainter (nuevo en v4.5, hasta v6.0.2)
Nombre de la clase encargada de dibujar las vistas. Ha de implementar
org.openxava.web.layout.ILayoutPainter
Hasta v5.4.1:
org.openxava.web.layout.impl.DefaultLayoutPainter
A partir de v5.5: null (por tanto usa JSP)
maxSizeForTextEditor
Limita el tamaño del campo de entrada para propiedades que representen textos largos
100
messagesOnTop (nuevo en v4.5. hasta v5.7.1)
Si es true los errores, advertencias y mensajes son mostrados en la parte superior de la página, si es false son mostrados al pie de la página. A partir de v5.8 se puede user CSS para poner los mensajes abajo.
true
readOnlyAsLabel

false
showIconForViewReadOnly (nuevo en v4.6)


showLabelsForToolBarActions (nuevo en v4m6)
Si es false, la barra de botones no despliega lo nombre de las acciones, sólo las imágenes
true
useIconsInsteadOfImages (nuevo en v5.4)
Cuando se especifique un icono y una imagen para una acción, se usará el icono
true
flowLayout (nuevo en v5.7)
Si es true la disposición de los campos se ajusta al tamaño de la página, ignorando los , ; # de @View
false
showDefaultActionInBottom (nuevo en v5.8)
Si es true la acción por defecto aparece como la primera acción abajo, incluso si ya está en la barra de botones superior
true

Listas y Colecciones
addColumnsPageRowCount (hasta v5.1.1)
Limita el numero de propiedades seleccionables para ser adicionadas a las columnas de las listas o propiedades
100
customizeList (nuevo en v4m5)
Si es false, no se permite personalizar las columnas de la lista
true
detailOnBottomInCollections

false
ignoreAccentsForStringArgumentsInConditions
(nuevo en v4m6)
Si es true Ignora las acentuaciones en las condiciones de lista y colecciones
false
pageRowCount
Default number of objects to show in lists and collections
10
resizeColumns (nuevo en v4m5)
Si es false, No se permite cambiar el tamaño de las columnas
true hasta v5.9.1, false a partir de v6.0
saveAndStayForCollections (nuevo en v4m6)
Si es false, el boton grabar y continuar no es mostrado cuando adicionan elementos a collecciones
true
showCountInList

true
showIconForViewReadOnly

true
showFilterByDefaultInList
Si es true, la fila de filtrar se muestra inicialmente en las listas, El usuario siempre tiene la opción de mostrar / ocultar la fila de filtrado
true
showFilterByDefaultInCollections (quitada a partir de v6.0)
Si es true,
la fila de filtrar se muestra inicialmente en las colecciones, El usuario siempre tiene la opción de mostrar / ocultar la fila de filtrado
true
summationInList (nuevo en v4.3)
Si es true Se muestra una fila de totales al final de la lista, bajo los campos numericos. El usuario puede manualmente encender o apagar los totales para cada columna
true
tabAsEJB

false
toUpperForStringArgumentsInConditions
Si es true se convierten a mayusculas los argumentos de busqueda en las listas y colecciones. Aunque esto permite las busquedas de datos independientemente de que esten en mayusculas o minusculas, puede producir bajos rendimientos con algunos manejadores de base de datos
true
filterOnChange (nuevo en v4.8)
El filtrado se realiza automáticamente al seleccionar una opción de un combo, sin pulsar en el botón de filtrar
true

Ayuda
helpAvailable (nuevo en v5.6)
Si es true un icono para acceder a la ayuda se muestra en el módulo
false since v6.0, true until v5.9.1
helpInNewWindow (nuevo en v4m5)
Si es true la página de ayuda se muestra en una nueva ventana, si es false, la página de ayuda es abierta en la ventana actual
true
helpPrefix (nuevo en v4m5)
Prefijo para la generación del URL de ayuda

helpSuffix (nuevo en v4m5)
Sufijo para la generación del URL de ayuda


Estereotipo FILE/ARCHIVO
filePersistorClass
Clase encargada de almacenar los archivos adjuntos
org.openxava.web.editors.FileSystemPersistor
filesPath
Directorio de almacenamiento de los archivos, en caso no se use base de datos.


Estereotipo COORDENADAS/COORDINATES (nuevo en v6.6)
mapsTileProvider
La URL del proveedor de imágenes de mapa (tile provider). Puedes usar un tile provider de OpenTopoMap (https://b.tile.opentopomap.org/{z}/{x}/{y}.png), MapBox (https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=YOUR_ACCESS_TOKEN), Stamen (http://tile.stamen.com/toner/{z}/{x}/{y}.png), OpenStreeMap (https://tile.openstreetmap.org/{z}/{x}/{y}.png) o Thunderforest (https://tile.thunderforest.com/neighbourhood/{z}/{x}/{y}.png?apikey=YOUR_API_KEY), entre otros. Te cuidado con cumplir con los términos de servicio del proveedor correspondiente.  https://b.tile.opentopomap.org/{z}/{x}/{y}.png
mapsAttribution
Texto de atribución a mostrar en una esquina del mapa. Depende del proveedor que uses. Asegurate de usar la atribución correcta.
Map data © OpenStreetMap contributors, Imagery © OpenTopoMap (CC-BY-SA)
mapsTileSize
Ancho y alto de la imagen en la rejilla.
256
mapsZoomOffset
El número de zoom usado en la URL será ajustado según este valor.
0

Reportes
reportParametersProviderClass
Clase para obtener los parametros para los informes. Tiene que implementar IReportParametersProvider o IRequestReportParametersProvider.
org.openxava.util.DefaultReportParametersProvider

Content Security Policy (CSP)
trustedHostsForImages (nuevo en v7.1.2)
Lista de sitios, separados por comas, que se pueden utilizar como origen para las imágenes. Se añade a img-src de la Política de Seguridad de Contenido (Content Security Policy, CSP). Puedes utilizar cualquier <host-source> como se explica en la documentación de CSP.

trustedHostsForScripts (nuevo en v7.1.2)
Lista de sitios, separados por comas, que se pueden utilizar como origen para los scripts. Se añade a script-src de la Política de Seguridad de Contenido (Content Security Policy, CSP). Puedes utilizar cualquier <host-source> como se explica en la documentación de CSP.
trustedHostsForStyles (nuevo en v7.1.2)
Lista de sitios, separados por comas, que se pueden utilizar como origen para los archivos CSS. Se añade a style-src de la Política de Seguridad de Contenido (Content Security Policy, CSP). Puedes utilizar cualquier <host-source> como se explica en la documentación de CSP.
trustedHostsForFrames (nuevo en v7.1.2)
Lista de sitios, separados por comas, que se pueden utilizar como origen para los frames e iframes. Se añade a frame-src de la Política de Seguridad de Contenido (Content Security Policy, CSP). Puedes utilizar cualquier <host-source> como se explica en la documentación de CSP.
unsafeEvalInScripts (nuevo en v7.3) Si es true, los encabezados de la Content Security Policy se configuran para permitir el uso de eval() inseguro en el código JavaScript. Esto permitiría la ejecución de código malicioso en la página web de la aplicación, por lo que es recomendable reescribir tu código JavaScript para no usar eval() en lugar de poner esta propiedad a true. false
turnOffWebSecurity (nuevo en v7.2) Si es true las cabeceras de Content Security Policy no se envían. Esto permitiría la ejecución de código malicioso en la página web de la aplicación, por eso es aconsejable utilizar las propiedades de arriba (las trustedHostForXXXX) antes de poner turnOffWebSecurity a true. false

Miscelánea
csvEncoding (nuevo en v4.2.1)
Porque es imposible obtener la codificación del cliente, que es usada por Excel al abrir el archivo. UTF-8, ISO-8859-1

csvSeparator

;
hibernateJavaLoggingLevel
Nivel para la bitácora de Hibernate. Los valores pueden ser: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL, OFF
INFO
javaLoggingLevel
Nivel para la bitácora de Java. Los valores válidos son: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL, OFF
INFO
componentParsersClasses (nuevo en v5.6)
Lista de clases separadas por comas para analizar los componentes, tienen que implementar
org.openxava.component.parse.IComponentParser
org.openxava.component.parse.XMLComponentParser, org.openxava.component.parse.AnnotatedClassParser
connectionRefinerClass (nuevo en v5.6)
Clase para crear un org.openxava.util.IConnectionRefiner para refinar las conexiones JDBC justo después de obtenerlas de la fuente de datos y antes de usarlas.

accessTrackerProvidersClasses (nuevo en v5.9)
Lista de clases separadas por comas usadas para monitorear cada cambio o acceso de lectura hecho por los usuarios a los datos. Las clases tienen que implementar org.openxava.util.IAccessTrackerProvider. Ya hay algunos proveedores incluidos en OpenXava como org.openxava.util.EmailNotificationsAccessTrackerProvider y org.openxava.util.LogAccessTrackerProvider.

enterMovesToNextField (nuevo en v6.4)
Si true la tecla INTRO (ENTER) mueve el foco al siguiente campo, como la tecla TAB, en lugar de aceptar el formulario.
false
applicationPort (nuevo en v6.4.2) El puerto usado por el lanzador de la aplicación (la clase _Run_TuAplicacion). 8080
defaultDescriptionPropertiesValueForDescriptionsList (nuevo en v7.1) Nombres de las propiedades a mostrar en el combo de un @DescriptionsList cuando el atributo descriptionProperties se omite. descripcion, description, nombre, name