<?xml version = "1.0" encoding = "ISO-8859-1"?> <!DOCTYPE editors SYSTEM "dtds/editors.dtd"> <editors> <editor .../> ... </editors>Simply it contains the definition of a group of editors, and an editor is defined like this:
<editor name="name" <!-- 1 New in v2.1.3 --> url="url" <!-- 2 --> format="true|false" <!-- 3 --> depends-stereotypes="stereotypes" <!-- 4 --> depends-properties="properties" <!-- 5 --> frame="true|false" <!-- 6 --> always-reload="true|false" <!-- 7 New in v3.1.2 --> composite="true|false" <!-- 8 New in v3.1.3 --> icon="icon" <!-- 9 New in v5.7 --> init-action="Controller.action" <!-- 10 New in v5.7 --> release-action="Controller.action" <!-- 11 New in v5.7 --> selectable-items="true|false" <!-- 12 New in v5.7 -->
default-label-format="normal|small|no-label" <!-- 13 New in v7.4 -->
> <property ... /> ... <!-- 14 --> <formatter ... /> <!-- 15 --> <list-formatter ... /> <!-- 16 New in v3.1.4 --> <for-stereotype ... /> ... <!-- 17 -->
<for-annotation ... /> ... <!-- 18 New in v6.6 -->
<for-type ... /> ... <!-- 19 -->
<for-model-property ... /> ... <!-- 20 --> <for-reference ... /> ... <!-- 21 New in v3.1.3 --> <for-collection ... /> ... <!-- 22 New in v3.1.3 --> <for-tab ... /> ... <!-- 23 New in v4.6 -->
<for-valid-values /> <!-- 24 New in v2.1.2 --> <for-references /> <!-- 25 New in v3.1.3 --> <for-collections /> <!-- 26 New in v3.1.3 --> <for-element-collections /> <!-- 27 New in v5.0 --> <for-tabs /> <!-- 28 New in v4.6 -->
</editor>
<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>Here a group of basic types is assigned to the editor textEditor.jsp (you can find it in openxava/src/main/resources/META-INF/resources/xava/editors). The JSP code of this editor is:
<%@ 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 Ignored since v7.2, so no longer needed 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 Ignored since v7.2 --> /> <% } else { %> <%=fvalue%> <% } %> <% if (!editable) { %> <input type="hidden" name="<%=propertyKey%>" value="<%=fvalue%>"> <% } %>A JSP editor receives a set of parameters and has access to attributes that allows to configure it in order to work suitably with OpenXava. First you can see how it gets propertyKey (1) that is used as HTML id. From this id you can access to MetaProperty (2) (that contains meta information of the property to edit). The fvalue (3) attribute contains the value already formated and ready to be displayed. Align (4) and editable (5) are obtained too. Also you need to obtain a JavaScript (6) fragment to put in the HTML editor (since v7.2 you don't need to specify script, it is ignored). You have to specify tabindex="1" (7) in order that the editors would be in the correct tab order (new in v4.5.1).
<editor url="textEditor.jsp"> <formatter class="org.openxava.formatters.UpperCaseFormatter"/> <for-type type="java.lang.String"/> </editor>In this way you are overwriting the OpenXava behavior for properties of String type, now all Strings are displayed and accepted in upper-cases. Let's see the code of the formatter:
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(); } }A formatter must implement IFormatter (1) or IMetaPropertyFormatter (new in v5.9), this forces you to write a format() (2) method to convert the property value (that can be a Java object) to a string to be rendered in HTML; and a parse() (3) method to convert the string received from the submitted HTML form into an object suitable to be assigned to the property.
@Stereotype("REGIONS") private String [] regions;Then you need to add the next entry to your stereotype-type-default.xml file:
<for stereotype="REGIONS" type="String []"/>
And to define in your editor in your editors.xml file:<editor url="regionsEditor.jsp"> <!-- 1 --> <property name="regionsCount" value="3"/> <!-- 2 --> <formatter class="org.openxava.formatters.MultipleValuesByPassFormatter"/> <!-- 3 --> <for-stereotype stereotype="REGIONS"/> </editor>regionsEditor.jsp (1) is the JSP file to render the editor. You can define properties that will be sent to the JSP as request parameters (2). And the formatter must implement IMultipleValuesFormatter, that is similar to IFormatter but it uses String [] instead of String. In this case we are using a generic formatter that simply do a bypass.
<%@ 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"); // Ignored since v7.2, no longer needed boolean label = org.openxava.util.XavaPreferences.getInstance().isReadOnlyAsLabel(); if (editable || !label) { String sregionsCount = request.getParameter("regionsCount"); 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%>> <%-- Not used since 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]%>"> <% } } %>As you see it is like defining a single value editor, the main difference is that the formatted value (1) is an array of strings (String []) instead of a simple string (String).
<%@ 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"); // Ignored since v7.2, no longer needed boolean label = org.openxava.util.XavaPreferences.getInstance().isReadOnlyAsLabel(); if (editable || !label) { String sregionsCount = request.getParameter("regionsCount"); 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%> <%-- Not used since 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]%>"> <% } } %>
<editor url="colorEditor.jsp"> <for-reference model="Color"/> </editor>With the above code you say that any reference to Color entity must be displayed and edited using colorEditor.jsp (for using an editor only for a concrete reference in a concrete entity look at Choosing an editor section in chapter about View).
<%@page import="java.util.Iterator"%>
<%@page import="org.openxava.test.model.Color"%>
<%
String propertyKey = request.getParameter("propertyKey"); // Id of the key property of the reference (1)
Object value = request.getAttribute(propertyKey + ".value"); // You can use 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>
<%
}
%>
<editor name="MyReference" url="myReferenceEditor.jsp" frame="true" composite="true"> <for-references/> </editor>Since you have marked the editor with <for-references/> now all the references in your application will be displayed using your myReferenceEditor.jsp. This is a simple way to customize the behaviour of the OpenXava UI generator.
<editor url="blogCommentsEditor.jsp"> <for-collection model="BlogComment"/> </editor>With the above code you say that any collection of BlogComment entities must be displayed and edited using blogCommentsEditor.jsp (for using an editor only for a concrete collection in a concrete entity look at Choosing an editor section in chapter about View). <for-collection /> works for @OneToMany/@ManyToMany and @ElementCollection collections.
<jsp:include page="collectionEditor.jsp"> <jsp:param name="listEditor" value="blogCommentsListEditor.jsp"/> </jsp:include>This is a typical way to create a collection editor, you call to collectionEditor.jsp (the default OpenXava editor for collections) sending as listEditor argument a JSP that contains the editor for the list part. In this way you have all the actions and default behaviour for collections for free, so you only have to do the rendering of the list.
<%@ 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 to access to the view object of the collection View collectionView = (View) context.get(request, viewObject); // We get the collection view by means of context View rootView = collectionView.getRoot(); // In this case we use the root view, the view of Blog Map key = rootView.getKeyValues(); if (Is.empty(key)) { %> There are no comments <% } else { // If the key has value, then we render the collection of comments Blog blog = (Blog) MapFacade.findEntity("Blog", key); String action = request.getParameter("rowAction"); // rowAction is the action to edit or view each element String actionArgv = ",viewObject=" + viewObject; %> These are the comments:<br/> <% DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locales.getCurrent()); int f=0; for (Iterator it = blog.getComments().iterator(); it.hasNext(); f++) { BlogComment comment = (BlogComment) it.next(); %> <i><b><big>Comment at <%=df.format(comment.getDate())%></big></b></i> <xava:action action='<%=action%>' argv='<%="row=" + f + actionArgv%>'/> <p> <i><%=comment.getBody()%></i> </p> <hr/> <% } } %>This editor draw the blog comments as simple texts with a date as header.
<%@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 is the id of the view of the parent object View view = (View) context.get(request, viewObject); // view is the view of Carrier, the parent of the collection Carrier carrier = (Carrier) MapFacade.findEntity("Carrier", view.getKeyValues()); %> The fellows of <%=carrier.getName()%> are:<br> <ul> <% for (Iterator it = carrier.getFellowCarriers().iterator(); it.hasNext(); ) { Carrier fellow = (Carrier) it.next(); %> <li><%=fellow.getName()%></li> <% } %> </ul>In this case you write the code for render the complete collection, if you wish to have some actions for working with the collection you must put it yourself. Beware, because viewObject here is the view of the object that contains the collection, not the view of the collection itself.
<editor name="MyCollection" url="myCollectionEditor.jsp"> <for-collections/> </editor> <editor name="MyElementCollection" url="myElementCollectionEditor.jsp"> <for-element-collections/> <!-- New in v5.0 --> </editor>Now all @OneToMany/@ManyToMany collections in your application will be displayed using your myCollectionEditor.jsp and all @ElementCollection collections using your myElementCollectionEditor.jsp.
<editor url="corporationEmployeeListEditor.jsp"> <for-tab model="CorporationEmployee"/> </editor>With the above code you say that all tabs (all the lists) for CorporationEmployee entity must be displayed and edited using corporationEmployeeListEditor.jsp (for using an editor only for a concrete tab of an entity look at Choosing an editor section).
<%@ 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', 'CorporationEmployee'," + "false, false, 'CorporationEmployee.filter', 'segment='+this.value)"; %> <select name="<xava:id name='chooseSegment'/>" onchange= "<%=action%>"> <option value="all" <%=all%>>All employees</option> <option value="low" <%=low%>>Low salary employees</option> <option value="high" <%=high%>>High salary employees</option> </select> <jsp:include page="listEditor.jsp"/>Note that this editor includes listEditor.jsp at the end. listEditor.jsp is the default editor for list mode, so in this case we only refine the standard list adding a combo to choose a custom filter. However, you can create your own list editor from scratch, for example, the following editor, customerCardListEditor.jsp, shows a list customer as a row of cards:
<%@ 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="customer-card"> <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> <% } %>For this editor we use a CSS class, customer-card (inline style is not allowed since v7.1), put this CSS class in a customerCardListEditor.css file inside the folder src/main/webapp/xava/editors/style (web/xava/editors/style in v6 or older) folder of your project, maybe you need to create the style folder the first time:
.customer-card {
border: 2px solid rgb(130, 143, 149);
display: inline-block;
padding: 10px;
margin-bottom: 10px;
}
<editor name="MyList" url="myListEditor.jsp"> <for-tabs/> </editor>Since you have marked the editor with <for-tabs/> now all the tabs in your application will be displayed using your myListEditor.jsp. This is a simple way to customize the behaviour of the OpenXava UI generator.
<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>And the next declaration in the editors.xml of your project:
<editor name="MyCards" url="myCardsEditor.jsp" icon="view-module"> <for-tabs/> </editor>Your user will have three formats to choose in the list:
<editor name="MyEditor" url="myEditor.jsp" icon="puzzle"> <for-tabs>
<has-type type="java.util.Date">
<has-type type="java.time.LocalDate">
<has-annotation annotation="DateTime">
<has-stereotype stereotype="DATETIME">
</for-tabs> </editor>
package com.yourcompany.invoicing.annotations;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface Colorful {
String color() default "black";
}
@Column(length=40) @Required
@Colorful(color="green")
String name;
<editor name="Colorful" url="colorfulEditor.jsp">
<property name="background" value="yellow"/>
<for-annotation annotation="com.yourcompany.invoicing.annotations.Colorful"/>
</editor>
<%
String background = request.getParameter("background"); // Read property from editors.xml
String color = request.getParameter("color"); // Read the attribute from the @Colorful annotation
%>
<span class="colorful-color-<%=color%> colorful-background-<%=background%>">
<jsp:include page="textEditor.jsp"/>
</span>
.colorful-color-black input { color: black; }
.colorful-background-black input { background: black; }
.colorful-color-white input{ color: white; }
.colorful-background-white input{ background: white; }
.colorful-color-red input{ color: red; }
.colorful-background-red input{ background: red; }
.colorful-color-green input{ color: green; }
.colorful-background-green input{ background: green; }
.colorful-color-blue input{ color: blue; }
.colorful-background-blue input{ background: blue; }
.colorful-color-yellow input{ color: yellow; }
.colorful-background-yellow input{ background: yellow; }
.colorful-color-orange input{ color: orange; }
.colorful-background-orange input{ background: orange; }
.colorful-color-purple input{ color: purple; }
.colorful-background-purple input{ background: purple; }
.colorful-color-gray input{ color: gray; }
.colorful-background-gray input{ background: gray; }
.colorful-color-pink input{ color: pink; }
.colorful-background-pink input{ background: pink; }
package com.yourcompany.invoicing.annotations;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface Colorful {
/**
* List of comma separated view names where this annotation applies. <p>
*
* Exclusive with notForViews.<br>
* If both forViews and notForViews are omitted then this annotation
* apply to all views.<br>
* You can use the string "DEFAULT" for referencing to the default
* view (the view with no name).
*/
String forViews() default "";
/**
* List of comma separated view names where this annotation does not apply. <p>
*
* Exclusive with forViews.<br>
* If both forViews and notForViews are omitted then this annotation
* apply to all views.<br>
* You can use the string "DEFAULT" for referencing to the default
* view (the view with no name).
*/
String notForViews() default "";
String color() default "black";
}
@Column(length=40) @Required
@Colorful(forViews="Complete, Simple", color="green")
String name;
<input ... onclick="f()"/> <!-- NOT ALLOWED SINCE v7.1 -->
Instead you have to attach the events from the code in your JS files. For your JavaScript code create a file called myEditor.js (or whatever name you want), and put it in src/main/webapp/xava/editors/js (web/xava/editors/js for v6 or older) folder.openxava.addEditorInitFunction(function() { /* Here your initialization code for your editor. That is the things your usually put in onload JavaScript event or $(function() { ... }) of jQuery */ ... });You see how using openxava.addEditorInitFunction() to register an initialization function. The onload JavaScript event or ready() event of jQuery does not work, because no page is loaded, instead the editor is generated in the server, loaded via AJAX and inserted in the already displayed page.
openxava.addEditorDestroyFunction(function() { // New in v4.8.1 /* Here the destroy code for your editor. This is to free resources obtained by the editor. */ ... });
Since v7.1 you can also define a function to call just after each AJAX request done by OpenXava for your editor in your myEditor.js file:
<input class="my-editor" type="button" value="Say hello"/>
openxava.addEditorInitFunction(function() {
$(".my-editor").click(function() {
alert("Hello");
});
});
@Stereotype("FAMILY") private int familyNumber; @Stereotype("SUBFAMILY") private int subfamilyNumber;And in your editors.xml put:
<editor url="descriptionsEditor.jsp"> <!-- 10 --> <property name="model" value="Family"/> <!-- 1 --> <property name="keyProperty" value="number"/> <!-- 2 --> <property name="descriptionProperty" value="description"/> <!-- 3 --> <property name="orderByKey" value="true"/> <!-- 4 --> <property name="readOnlyAsLabel" value="true"/> <!-- 5 --> <for-stereotype stereotype="FAMILY"/> <!-- 11 --> </editor> <!-- It is possible to specify dependencies from stereotypes or properties --> <editor url="descriptionsEditor.jsp" <!-- 10 --> depends-stereotypes="FAMILY"> <!-- 12 --> <!-- <editor url="descriptionsEditor.jsp" depends-properties="familyNumber"> <!-- 13 --> --> <property name="model" value="Subfamily"/> <!-- 1 --> <property name="keyProperty" value="number"/> <!-- 2 --> <property name="descriptionProperties" value="number, description"/> <!-- 3 --> <property name="condition" value="${familyNumber} = ?"/> <!-- 6 --> <property name="parameterValuesStereotypes" value="FAMILY"/> <!-- 7 --> <!-- <property name="parameterValuesProperties" value="familyNumber"/> <!-- 8 --> --> <property name="descriptionsFormatter" <!-- 9 --> value="org.openxava.test.formatters.FamilyDescriptionsFormatter"/> <for-stereotype stereotype="SUBFAMILY"/> <!-- 11 --> </editor>When you show a view with this two properties (familyNumber and subfamilyNumber) OpenXava displays a combo for each property, the family combo is filled with all families and the subfamily combo is empty; and when the user chooses a family, then the subfamily combo is filled with all the subfamilies of the chosen family.
<module name="SellersJSP" folder="invoicing.variations"> <model name="Seller"/> <view name="ForCustomJSP"/> <!-- 1 --> <web-view url="custom-jsp/seller.jsp"/> <!-- 2 --> <controller name="Typical"/> </module>If you use web-view (2) on defining your module, OpenXava uses your JSP to render the detail, instead of generating the view automatically. Optionally you can define an OpenXava view using view (1), this view is used to know the events to throw and the properties to populate, if not it is specified the default view of the entity is used; although it's advisable to create an explicit OpenXava view for your JSP custom view, in this way you can control the events, the properties to populate, the focus order, etc explicitly. You can put your JSP inside src/main/webapp/custom-jsp (or other of your choice) folder of your project (web instead of src/main/webapp for versions older than v7.0), and it can be as this one:
<%@ include file="../xava/imports.jsp"%> <table> <tr> <td>Number: </td> <td> <xava:editor property="number"/> </td> </tr> <tr> <td>Name: </td> <td> <xava:editor property="name"/> </td> </tr> <tr> <td>Level: </td> <td> <xava:editor property="level.id"/> <xava:editor property="level.description"/> </td> </tr> </table>You are free to create your JSP file as you like, but it can be useful to use OpenXava taglibs, in this case, for example the <xava:editor/> taglib is used, this renders an editor suitable for the indicated property, furthermore add the needed javascript to throw the events. If you use <xava:editor/>, you can manage the displayed data using xava_view (of org.openxava.view.View type) object, therefore all standard OpenXava controllers (including CRUD) work.
<xava:editor property="propertyName" <!-- 1 --> editable="true|false" <!-- 2 New in v2.0.1 --> throwPropertyChanged="true|false" <!-- 3 New in v2.0.1 --> />
<xava:action action="controller.action" argv="argv"/>
The action attribute indicates the action to execute, and the argv attribute (optional) allows you to put values to some properties of the action before execute it. One example:<xava:action action="CRUD.save" argv="resetAfter=true"/>
When the user clicks on it, then it executes the action CRUD.save, before it puts true to the resetAfter property of the action.<xava:action action=""/>
In this case the tag has no effect and no error is produced. This feature may be useful if you fill the name of the action dynamically (that is action=”<%=mycode()%>”), and the value can be empty in some cases.<xava:message key="message_key" param="messageParam" intParam="messageParam"/>
The message is searched first in the message resource files of your project (yourproject/src/main/resources/i18n/yourproject-messages_en.properties for v7 or better, and YourProject/i18n/YourProject-messages.properties for v6 or older) and if it is not found there then it's searched in the default OpenXava messages (openxava/src/main/resources/i18n/Messages_en.properties for v7 or better, and OpenXava/i18n/Messages.properties for v6 or older).<xava:message key="list_count" intParam="<%=totalSize%>"/>
<xava:label key="memberName"/>
The message is searched first in the label resource files of your project (yourproject/src/main/resources/i18n/yourproject-labels_en.properties for v7 or better, and YourProject/i18n/YourProject-labels.properties for v6 or older) and if it is not found there then it's searched in the default OpenXava labels (openxava/src/main/resources/i18n/Labels_en.properties for v7 or better, and OpenXava/i18n/Labels.properties for v6 or older).<tr> <td>Number: </td><td> <xava:editor property="number"/> </td> </tr>You can write this:
<tr> <td><xava:label key="number"/>: </td><td> <xava:editor property="number"/> </td> </tr>And get the label translated.
<xava:descriptionsList reference="referenceName" <!-- 1 -->
readOnlyAsLabel="true|false" <!-- 2 New in v6.0.1 -->
/>
<tr> <td>Level: </td> <td> <xava:descriptionsList reference="level"/> </td> </tr>In this case level is a reference of the current model (for example Seller). A combo is shown with all available levels.
<%@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>
Property |
Description |
Default |
E-Mailing |
||
emailAsUserNameInPortal (removed since v7.0) |
false |
|
smtpHost |
Host for mail send through SMTP provider |
|
smtpHostTrusted (new in v4.7) |
if true a mail server with an expired certificate can be used |
false |
smtpPort |
Port for mail send through SMTP provider |
|
smtpUserId |
User id for connecting to mail SMTP provider |
|
smtpUserPassword |
User password for connecting to the SMTP server |
|
smtpStartTLSEnable (new in v5.6) |
If true, enables the use of the STARTTLS command (if supported by the server) to switch the connection to a TLS-protected connection before issuing any login commands. Note that an appropriate trust store must configured so that the client will trust the server's certificate. |
false |
smtpFromEmail (new in v6.2) |
Value for the from field of the message. Use if you need to use a different value for user id and for from field (useful for AWS SES alike API environments). |
The value of smtpUserId |
Persistence |
||
defaultPersistenceUnit |
Persistence unit to be used as default |
default |
jpaCodeInPOJOs (removed since v5.6) |
Depends on persistence provider |
|
mapFacadeAsEJB |
false |
|
mapFacadeAutoCommit |
false |
|
persistenceProviderClass (removed since v5.6) |
Defines which class provides the persistence handling |
org.openxava.model.impl.JPAPersistenceProvider |
Labels, Messages and Locales |
||
i18nWarnings |
false |
|
portletLocales (removed since v7.0) | Locales for portlet generation and deployment |
bg, ca, de, en, es, fr, in, it, ja, ko, nl, pl, pt, ru, sv, zh |
Application and Controllers |
||
defaultLabelFormat |
Possibles values for defaultLabelFormat are: NORMAL, SMALL and NO_LABEL |
NORMAL |
defaultLabelStyle |
It has defined: bold-label, italic-label. And you can define your own style. |
|
defaultModeController (new in v4m5) |
Possibles values for defaultModeController are Mode, DetailList, DetailOnly, ListOnly and SplitOnly; moreover your own custom controllers. If not specified, the default mode controller associated to the style is used |
Mode |
duplicateComponentWarnings |
On encountering duplicate components like controllers or modules, warning messages are written to the log |
true |
failOnAnnotationMisuse |
Throws error if properties, references or collections have non-applicable annotations |
true |
generateDefaultModules |
If true it is not required to define modules in application.xml, OX generates the modules' information automatically |
true |
Styling |
||
liferay6StyleClass (new in v4m6, removed since v7.0) |
Style class compatible with liferay 6 |
org.openxava.web.style.Liferay6Style |
liferay51StyleClass (removed since v7.0) | Style class compatible with liferay 5.1 |
org.openxava.web.style.Liferay51Style |
liferay41StyleClass (removed since v7.0) | Style class compatible with liferay 4.1 |
org.openxava.web.style.Liferay41Style |
liferay43StyleClass (removed since v7.0) | Style class compatible with liferay 4.3 |
org.openxava.web.style.Liferay43Style |
webSpherePortal61StyleClass (removed since v7.0) | Style class compatible with WebSphere Portal 6.1 |
org.openxava.web.style.WebSpherePortal61Style |
styleClass |
Class that handles the default UI element class assignment. |
org.openxava.web.style.XavaStyle (since v6.0) org.openxava.web.style.Liferay51Style (until v5.9.1) |
styleCSS |
URL of CSS file that provides a visual UI style. |
terra.css (since v6.0) liferay51/css/everything_unpacked.css (until v5.9.1) |
themes (new in v6.3) |
List of CSS files separated by comma of styles available for the user to choose as themes. If the value is empty the theme chooser is not available for the user. |
Empty |
Views and Layouts |
||
alignedByColumns (new in v4.7.1) |
If true all properties within views are displayed aligned by column same as using # on all views. Active only for default implementations of layoutParser & layoutPainter. |
false |
buttonsForNoImageActions |
If true when an action has no image it uses a button for display it, else it uses a link. |
false |
layoutParser (new in v4.5, until v6.0.2) |
Name of a layout parser class. Must implement org.openxava.web.layout.ILayoutParser |
Until v5.4.1: org.openxava.web.layout.impl.DefaultLayoutParser Since v5.5: null (so a JSP parser is used) |
layoutPainter (new in v4.5, until v6.0.2) |
Name of a layout painter class. org.openxava.web.layout.ILayoutPainter |
Until v5.4.1: org.openxava.web.layout.impl.DefaultLayoutPainter Since v5.5: null (so a JSP painter is used) |
maxSizeForTextEditor |
On large text (String) properties limits the display size to this value |
100 |
messagesOnTop (new in v4.5, until v5.7.1) |
If true errors, warnings and messages are displayed at the top, if false they are displayed at the bottom. Since v5.8 you can use CSS to put the messages on bottom. |
true |
readOnlyAsLabel |
false |
|
showIconForViewReadOnly (new in v4.6) |
||
showLabelsForToolBarActions (new in v4m6) |
If false the toolbar shows only the action images, no text is displayed |
true |
useIconsInsteadOfImages (new in v5.4) |
When both icon and image are defined for an action, the icon will be used |
true |
flowLayout (new in v5.7) |
If true adjusts the fields layout to the size of the page, ignoring the , ; # used in @View |
false |
showDefaultActionInBottom (new in v5.8) |
If true the default action is shown as the first action in bottom, even if it is already in top buttom bar |
true |
Lists and Collections |
||
addColumnsPageRowCount (until v5.1.1) |
Limits the number of selectable properties that can be added to the columns of lists and collections |
100 |
customizeList (new in v4m5) |
If false, list customization is disallowed |
true |
detailOnBottomInCollections |
false |
|
ignoreAccentsForStringArgumentsInConditions (new in v4m6) |
If true it ignores accents to string arguments for conditions in list and collections |
false |
pageRowCount |
Default number of objects to show in lists and collections |
10 |
resizeColumns (new in v4m5) |
If false, columns resizing is disabled |
true until v5.9.1, false since v6.0 |
saveAndStayForCollections (new in v4m6) |
If false, the save and stay button is hidden when adding elements to collections |
true |
showCountInList |
true |
|
showIconForViewReadOnly |
true |
|
showFilterByDefaultInList |
If true filter is show by default for list on init. The user always have the option to show or hide the filter |
true |
showFilterByDefaultInCollections (removed since v6.0) |
If true filter is show by default for collections on init. The user always have the option to show or hide the filter |
true |
summationInList (new in v4.3) |
If true, summary rows are shown at bottom of lists, under numerical columns. Users can manually turn on or off the totals at each column |
true |
tabAsEJB |
false |
|
toUpperForStringArgumentsInConditions |
If true upper case conversions are applied to string arguments for conditions in list and collections. If true, also the searching using list or collections are more flexible (the user can use indistinctly upper or lower case) but can be slower in some databases (because they cannot use index) |
true |
filterOnChange (new in v4.8) |
Filtering is done automatically when an option of a combo is chosen, without clicking on filter button |
true |
Help |
||
helpAvailable (new in v5.6) |
If true an icon to go to help is shown in the module |
false since v6.0, true until v5.9.1. |
helpInNewWindow (new in v4m5) |
If true the help page is opened in a new window, if false, the help page is opened in the current window |
true |
helpPrefix (new in v4m5) |
Help prefix for the help URL generation |
|
helpSuffix (new in v4m5) |
Help suffix for the help URL generation |
|
FILE/ARCHIVO Stereotype |
||
filePersistorClass |
Defines which class provides the storing of attachments. |
org.openxava.web.editors.FileSystemPersistor |
filesPath |
File storage directory, if no database is used. |
|
COORDINATES/COORDENADAS Stereotype (new in v6.6) |
||
mapsTileProvider |
The URL of the tile provider to generate maps. You can use tile providers from 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) or Thunderforest (https://tile.thunderforest.com/neighbourhood/{z}/{x}/{y}.png?apikey=YOUR_API_KEY), amongs others. Beware of comply with the terms of service of the corresponding provider. | https://b.tile.opentopomap.org/{z}/{x}/{y}.png |
mapsAttribution |
Attribution text to shown in a corner of the map. It depends on the tile provider you use. Be sure of using the correct attribution. |
Map data © OpenStreetMap contributors, Imagery © OpenTopoMap (CC-BY-SA) |
mapsTileSize |
Width and height of tiles in the grid. |
256 |
mapsZoomOffset |
The zoom number used in tile URLs will be offset with this value. |
0 |
Reporting |
||
reportParametersProviderClass |
Class that provides the report parameters. It must implement IReportParametersProvider or IRequestReportParametersProvider, |
org.openxava.util.DefaultReportParametersProvider |
Content Security Policy (CSP) |
||
trustedHostsForImages (new in v7.1.2) |
List of hosts, comma separated, that can be used as source for images. It is added to img-src of Content Security Policy. You can use any <host-source> as explained in the CSP doc. |
|
trustedHostsForScripts (new in v7.1.2) |
List of hosts, comma separated, that can be used as source for scripts. It is added to script-src of Content Security Policy. You can use any <host-source> as explained in the CSP doc. |
|
trustedHostsForStyles (new in v7.1.2) |
List of hosts, comma separated, that can be used as source for CSS files. It is added to style-src of Content Security Policy. You can use any <host-source> as explained in the CSP doc. |
|
trustedHostsForFrames (new in v7.1.2) |
List of hosts, comma separated, that can be used as source for frames and iframes. It is added to frame-src of Content Security Policy. You can use any <host-source> as explained in the CSP doc. |
|
unsafeEvalInScripts (new in v7.3) | If true, the Content Security Policy headers is set to allow the use of unsafe eval() in JavaScript code. This would allow the execution of malicious code on the application's web page, which is why it is advisable to rewrite your JavaScript code to not use eval() instead of put this property to true. | false |
turnOffWebSecurity (new in v7.2) | If true, the Content Security Policy headers are not sent. This would allow the execution of malicious code on the application's web page, which is why it is advisable to use the above properties (the trustedHostForXXXX) before setting turnOffWebSecurity to 'true'. | false |
Miscelaneous |
||
csvEncoding (new in v4.2.1) |
Because it's impossible to obtain the client encoding, that used by Excel to open the file. UTF-8, ISO-8859-1 |
|
csvSeparator |
; |
|
hibernateJavaLoggingLevel |
Logging level for hibernate. Valid values are: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL, OFF |
INFO |
javaLoggingLevel |
Logging level for java. Valid values are: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL, OFF |
INFO |
componentParsersClasses (new in v5.6) |
List of comma separated classes used for parsing the components, they must implement org.openxava.component.parse.IComponentParser |
org.openxava.component.parse.XMLComponentParser, org.openxava.component.parse.AnnotatedClassParser |
connectionRefinerClass (new in v5.6) |
Class to create an org.openxava.util.IConnectionRefiner to refine the JDBC connections just after get them from the data source and before use them. |
|
accessTrackerProvidersClasses (new in v5.9) |
List of comma separated classes used to track each change or read access done by users to data. The classes must implement org.openxava.util.IAccessTrackerProvider. There are already some providers included in OpenXava such as org.openxava.util.EmailNotificationsAccessTrackerProvider and org.openxava.util.LogAccessTrackerProvider. |
|
enterMovesToNextField (new in v6.4) |
If true the ENTER key moves the focus to the next field, like the TAB key, instead of accepting the form. |
false |
applicationPort (new in v6.4.2) | The port used by the application launcher (the _Run_YourApplication class). | 8080 |
defaultDescriptionPropertiesValueForDescriptionsList (new in v7.1) | Names of the properties to show in a combo for a @DescriptionsList when descriptionProperties attribute is missing. | descripcion, description, nombre, name |
currencySymbol (new in v7.4) |
It allows defining the currency symbol for the entire application, regardless of the server's language |
Currency symbol corresponding to the application server's locale. |