Dynamic JSF UI Components Generation - java

I'm trying to solve the following problem:
Let's say that I have a settings.xml file that looks as follows:
<SETTINGS>
<username fieldType="TextField" possibleValues="*">username_value</username>
<roletype fieldType="DropDownList" possibleValues="normal,admin,agent">admin</roletype>
<active fieldType="RadioButtons" possibleValues="true,false">true</active>
<SETTINGS>
What I'm trying to achieve is the following:
1- When my page first loads, it will parse this xml file, and layout the UI components based on the fieldType and the possibleValues.
2- When my UI components are loaded, I should be able to configure the value of my fields, which will end up persisting in my settings.xml file.
Is there a ready library that does this? Or do I need to write the code for this myself?
Note: I'm restricted to using JSF 1.x
Thanks in advance.

First of all , i will recommend to change the structure of your XML file as:
<SETTINGS>
<controls>
<control label="username" fieldType="TextField">
<values></values>
<selvalue></selvalue>
</control>
<control label="roletype" fieldType="DropDownList">
<values>
<value>normal</value>
<value>admin</value>
<value>agent</value>
</values>
<selvalue></selvalue>
</control>
<control label="active" fieldType="RadioButtons">
<values>
<value>true</value>
<value>false</value>
</values>
<selvalue></selvalue>
</control>
Now use JAXB to parase this XML file to the different classed, where each xml tab will be act as one independent class.
like :
Settings :
private List<Control> controls;
Control :
String label; // Attribute
String fieldType; // Attribute
Values values; //Property
String selValue; //Property
Values :
List<Value> values; ////Property
Value :
String value; //Property
DynaCritSearchBean : A Bean Class
Settings settings;
Once the data is loaded in to the corresponding class, use the following logic to dynamically create the screen in your XHTML file :
<h:panelGrid>
<c:forEach var="control"
items="#{dynaCritSearchBean.settings.controls}">
<h:panelGroup>
<h:outputText value="#{control.label}" />
</h:panelGroup>
<h:panelGroup>
<c:choose>
<c:when test="#{control.fieldType eq 'TextField'}">
<h:inputText value="#{control.selvalue}" />
</c:when>
<c:when test="#{control.fieldType eq 'DropDownList'}">
<h:selectOneMenu value="#{control.selvalue}">
<f:selectItem itemValue="" itemLabel="--select--" />
<c:forEach var="selOneValue" items="#{control.values.values}">
<f:selectItem itemValue="#{selOneValue}"
itemLabel="#{selOneValue}" />
</c:forEach>
</h:selectOneMenu>
</c:when>
<!-- Same as above logic for Radio button -->
</c:choose>
</h:panelGroup>
</c:forEach>
</h:panelGrid>
Once you submit the form, all selected/entered values are set to corresponding selValue of each Control.
Now, in order to get the XML back, you can use same JAXB concept which is very simple.

Related

Do logic on apache tile attributes

In my apache tiles config file, I have a section like this:
<definition name="admin/*/*" extends="adminLayout">
<put-attribute name="key" cascade="true" value="{1}" />
</definition>
Then, in my JSP, I am would like to do some logic on the tile attribute.
Something like:
<c:if test="${key == 'value'}">
// do something
</c:if>
where key comes from the tile attribute.
How can I access this tile attribute inside the expression language?
I have tried
<c:set value="<tiles:insertAttribute name='key'/>" var="theKey"></c:set>
and
<c:if test="${<tiles:insertAttribute name='key'/> == 'value'}">
and both times the raw tiles xml is used as the comparing string - it doesn't get replaced by the attribute.
Use Tiles extras:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:tiles="http://tiles.apache.org/tags-tiles"
xmlns:tilesx="http://tiles.apache.org/tags-tiles-extras"
version="2.0">
<tilesx:useAttribute id="keyJspVariable" name="key" classname="java.lang.String" />
<c:if test="${keyJspVariable== 'value'}">
// do something
</c:if>
Documentation example: https://tiles.apache.org/framework/tutorial/advanced/list-attributes.html

Get value of a property inside jstl tag

I'm developing a simple tag library in order to centralize the creation of form components.
In my custom tag I need to get the value of the backing object mapped field.
Here is how I pass the field name value to my library:
<jsp:directive.attribute name="field" type="java.lang.String" required="true" rtexprvalue="true" description="The field exposed from the form backing object" />
Inside my tag library, using <form:hidden path="${field}.id" /> from spring tag library works, but how can I get same value not using that library? I do not want to have an input type hidden mapped in my form, but only retrieve the value of that field name.
Thanks for any hints.
You can try the spring:eval tag
<jsp:directive.attribute name="object" type="java.lang.Object" required="true" description="The form backing object" />
<jsp:directive.attribute name="field" type="java.lang.String" required="true" description="The field name" />
<spring:eval expression="object[field]" />

Composition is not rendered in Richfaces tabPanel

I am a user of JSF and Richfaces. I will simplify the code about my question to make things easier.
I have a composition named 'mytab.xhtml' defined like following:
<cc:interface>
<cc:attribute name="header" required="true"/>
</cc:interface>
<cc:implementation>
<rich:tab id="my-tab" header="#{cc.attrs.header}" >
<cc:insertChildren />
</rich:tab>
</cc:implementation>
This composition is used in another xhtml file like following:
<rich:tabPanel id="tp" switchType="ajax" headerPosition="top" >
<ic:mytab id="tab1" header="header1">
<h:outputText>content1</h:outputText>
</ic:mytab>
<ic:mytab id="tab2" header="header2">
<h:outputText>content1</h:outputText>
</ic:mytab>
</rich:tabPanel>
But it is very strange that the tab is not rendered at all.
To find the reason, if I add an outputText in the composition definition file like this:
<cc:interface>
<cc:attribute name="header" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputText>#{cc.attrs.header}</h:outputText>
<rich:tab id="my-tab" header="#{cc.attrs.header}" >
<cc:insertChildren />
</rich:tab>
</cc:implementation>
The outputText will be rendered, but tab is not rendered.
Or, if I change one of the tab to richfaces tab directly:
<rich:tabPanel id="tp" switchType="ajax" headerPosition="top" >
<ic:mytab id="tab1" header="header1">
<h:outputText>content1</h:outputText>
</ic:mytab>
<rich:tab id="tab2" header="header2">
<h:outputText>content1</h:outputText>
</rich:tab>
</rich:tabPanel>
The first tab will not be rendered, but the second tab will be rendered.
Thank you if you could give me any help.
Composite components are rendered as own UINamingContainer. So between the UITabPanel and the UITab-component now is a UINamingContainer, UITab might not know what to do with it (same problem with datatable, by the way). What you can do is to use a classic facelet tag instead.

Javabean validation error inside JSF/PrimeFaces dialog

Recently I have update my application to JSF 2.1.7 and PrimeFaces 3.4.2. When the below dialog is used for adding a new group, I get an "Name size must be between 1 and 40" validation error, prior to saving the new group. It happens when I click the picker's add button. I understand that this message is shown because the validation failed. The validation error doesn't appear when I add immediate=true to p:commandButton. I don't know what triggered the validation.
<h:form id="formg" prependId="false">
<!-- messages -->
<p:growl id="msgsg" showDetail="true" />
<!-- data table -->
<ui:include src="/WEB-INF/flows/groupsTable.xhtml" />
<p:separator />
<!-- bottom tool bar -->
<ui:include src="/WEB-INF/flows/groupsToolBar.xhtml" />
<!-- preview, edit dialog -->
<ui:include src="/WEB-INF/flows/groupsDialog.xhtml" />
</h:form>
<p:dialog id="dialogg" header="#{groupsBean.dialogTitle}"
widgetVar="groupsDialog" dynamic="true" resizable="false" width="800"
height="600" showEffect="fade" hideEffect="fade" modal="true">
<p:ajax event="close" listener="#{groupsBean.refresh}"
immediate="true" update=":formg" global="false" process="#this" />
<p:tabView id="tabPicker">
<p:tab title="General">
<h:panelGrid id="displayg" columns="2">
<h:outputText value="#Group name*:" />
<p:inputText value="#{groupsBean.selectedGroup.name}" size="40"
readonly="#{!groupsBean.updatable}" maxlength="40" />
</h:panelGrid>
</p:tab>
<p:tab title="Members">
<ui:include src="/WEB-INF/custom/picker.xhtml">
... some params passed to picker
</ui:include>
</p:tab>
</p:tabView>
</p:dialog>
The picker is similar to <p:password> and it is made up from two p:dataTable components and 4 buttons between them. The buttons are grouped together with a h:panelGrid. The button attributes are similar. Here is button sample code:
<p:outputPanel autoUpdate="true">
<p:commandButton actionListener="#{eval.evaluateAsMethod(pickerAdd)}"
update="source, target, #{messages}" immediate="true"
disabled="#{pickerSourceDisabled}"
icon="ui-icon ui-icon-arrowthick-1-s" />
</p:outputPanel>
source, target are the ids of the two datatables. pickerAdd is passed as param with a value of groupsBean.picker.add. The tables contain FooDomain objects.
public class FooDomain implements Serializable {
...
#NotNull
#Size(min = 1, max = 40)
#Column(name = "NAME")
private String name;
...
}
The PrimeFaces <p:commandButton> processes by default the entire form (as in, process="#form"), so it would by default trigger all validations. Your validation error is coming from the #Size restriction on the property. If you would like to process only the button's own action, then you should add process="#this".
<p:commandButton ... process="#this" />
The immediate="true" can also be used to solve it, but it behaves under the covers somewhat different: the entire form is still processed, but the action is invoked in APPLY_REQUEST_VALUES phase instead of INVOKE_ACTION phase. And only the input components which also have immediate="true" set will also be processed and others will be skipped.

Primefaces 3.0 : TreeNode and ContextMenu

In my application, I have a tree with various object types (sources, tables, etc).
I'd like to enable a context menu for the different types of object (add, delete, edit etc).
How can I use context menu on tree nodes in Primefaces ?
Never did it in practice (I am still on Primefaces 2.x), but from theory the facelet code should look something like this:
<h:form>
<p:tree value="#{myBean.tree}" var="node" id="tree"
selectionMode="single" selection="#{myBean.selectedNode}">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
<p:contextMenu for="tree" id="menu">
<p:menuitem value="Add" actionListener="#{myBean.add}" />
...
</p:contextMenu>
</h:form>
Usage of p:contextMenu and p:tree is shown in Primefaces showcase.

Categories

Resources