jsf el expression to build methodname - jsf

Is something like that possibile to build the MethodName with a variable value?
<c:forEach value="#{db.pojo.classList}" var="v">
<c:forEach items="#{db.pojo.methodNamesList}" var="o">
<c:set var="superman" value="#{o}" />
#{v.[superman]}
</c:forEach>
</c:forEach >
... database.entity.list is a List of Generic classes.
List<?> list..
I can use the generic class if i know the Methodname.
<c:forEach value="#{db.pojo.classList}" var="v">
#{v.value}
</c:forEach >

#{v.[superman]}
Punch that period.
#{v[superman]}
That <c:set> is unnecessary, by the way.
#{v[o]}
I would only use more self-documenting variable names though. E.g.
#{bean[property]}
#{entity[field]}
See also:
Our EL wiki page

Related

Evaluation with <c:when> in data table doesn't work

I have searched and tried but this time I'm really stuck.
I am trying to build a simple datatable (primefaces) where the cell content can be of different types. There is a holder class for each cell content that can hold different entities and I want to use < c:choose> to check and display the right entity in the entity specific way.
The code looks like:
<p:dataTable emptyMessage="" value="#{date.getThreadContent(column.propertyID)}" var="content">
<p:column>
#{content.type}
<c:choose>
<c:when test="#{content.type == 'activity'}">
#{content.activity.name}
</c:when>
<c:when test="#{content.type == 'todo'}">
#{content.activity.name}
</c:when>
<c:otherwise>
Neither activity or todo
</c:otherwise>
</c:choose>
</p:column>
</p:dataTable>
The EL evaluation doesn't work regardless if I try a boolean or String values in the bean (I'm using String value in the code above).
So each time the content is not empty, the output first displays the correct content type from #{content.type} but then together with 'Neither activity or todo'.
I can also say that this data table itself represents a cell content in a parent data table (list of entities per date) that is not visible in this code as I try to isolate the problem.
Could it be that this type of expression cannot be done in a ?
Any help is appreciated.
Use JSF rendered tags to do your conditional display logic, it removes it from the DOM completely and makes validations easier.
Refer: http://docs.oracle.com/javaee/6/tutorial/doc/bnaik.html for EL expressions
Also a good explanation is provided by BalusC here: JSTL c:if doesn't work inside a JSF h:dataTable
<p:dataTable emptyMessage="" value="#{date.getThreadContent(column.propertyID)}" var="content">
<p:column>
#{content.type}
<h:outputText value="#{content.activity.name}" rendered="#{content.type == 'activity' or content.type == 'todo'}" />
<h:outputText value="Neither activity or todo" rendered="#{content.type != 'activity' and content.type != 'todo'}" />
</p:column>
</p:dataTable>

Best approach to render UI elements based on dataType

I am trying to render richfaces and jsf UI elements dynamically based on the dataType value.
Ex : I have a enum as below
public enum DataType {
DT_LONGLONG(1), DT_STRING(2), DT_LONG(3), DT_DATE(4), DS_EXTERNALREFERENCE(5),
DT_BOOLEAN(6), DT_FLOAT(7), DT_SHORT(8);
}
Then in xhtml page while iterating through the list of my custom objects, I check for the dataType and render the UI elements accordingly as below :
<c:if test="#{meaCompPartAttr.dataType.dataType == 2}">
<h:inputText />
</c:if>
<c:if test="#{(meaCompPartAttr.dataType.dataType == 1) or
(meaCompPartAttr.dataType.dataType == 3) or
(meaCompPartAttr.dataType.dataType == 8)}">
<h:inputText onkeyup="javascript:validateField(this, '#{tpMsgs.longRegularExpression}');">
<f:validateLongRange/>
</h:inputText>
</c:if>
<c:if test="#{meaCompPartAttr.dataType.dataType == 7}">
<h:inputText onkeyup="javascript:validateField(this, '#{tpMsgs.doubleRegularExpression}');">
<f:validateDoubleRange/>
</h:inputText>
</c:if>
<c:if test="#{meaCompPartAttr.dataType.dataType == 6}">
<h:selectBooleanCheckbox />
</c:if>
<c:if test="#{meaCompPartAttr.dataType.dataType == 4}">
<rich:calendar />
</c:if>
Because of this I usually get class cast exceptions like String to Boolean or Long to String etc. I assume this is happening coz jstl and jsf code do not run in sync.
Is there any other approach to render UI elements dynamically as proposed in the above sample?
So you're iterating using <ui:repeat> or <h:dataTable> or any other JSF iterating component instead of the JSTL <c:forEach>? Either use <c:forEach> instead, or use the rendered attribute instead of <c:if>.
See also:
JSTL in JSF2 Facelets... makes sense?
How to create dynamic JSF form fields

Concatenating strings within EL expression defined in an attribute of a facelets tag

I need to write an EL expression for an attribute which goes something like this:
#{cc.attrs.appreciatedByCurrentUser ? (cc.attrs.count +'<br/>'+ (cc.attrs.count-1)) : ((cc.attrs.count+1) +'<br/>'+ cc.attrs.count)}
Now the problem is that this gives an error as strings cannot be concatenated, the way I am doing it. So how can I rectify this?
I'm using JSF 2.0 with facelets.
EDIT :
I'm resolving the issue using the following inline javascript
<script type="text/javascript">
var count=#{cc.attrs.count};
document.write(#{cc.attrs.appreciatedByCurrentUser} ? (count-1) +'<br/>'+count : count+'<br/>'+ (count+1));
</script>
Can you think of any issue with this?
It is possible to concatenate Strings in EL using the java.lang.String.concat(String) method. Thus your code could look like:
<h:outputText value="#{cc.attrs.appreciatedByCurrentUser ? (''.concat(cc.attrs.count).concat('<br/>').concat(cc.attrs.count-1)) : (''.concat((cc.attrs.count+1)).concat('<br/>').concat(cc.attrs.count))}" escape="false" />
In this particular case however I would go with one of the options that Mr BalusC had suggested because the code above doesn't look quite elegant. In some cases knowing this technique could be useful, though.
I would hardly recommend using javascript as a workaround here.
String concatenation in EL is only possible by just inlining in the expression. The + operator is in EL exclusively a sum operator. Further, < and > are invalid characters in XML attributes, so you have to escape them (and instruct <h:outputText> to not escape them once again by escape="false"):
<h:outputText value="#{cc.attrs.count}<br/>#{cc.attrs.count-1}" escape="false" rendered="#{cc.attrs.appreciatedByCurrentUser}" />
<h:outputText value="#{cc.attrs.count+1}<br/>#{cc.attrs.count}" escape="false" rendered="#{!cc.attrs.appreciatedByCurrentUser}" />
Alternatively, you can also use <c:set> to alias the expression:
<c:set var="appreciated" value="#{cc.attrs.count}<br/>#{cc.attrs.count-1}" />
<c:set var="notAppreciated" value="#{cc.attrs.count+1}<br/>#{cc.attrs.count}" />
<h:outputText value="#{cc.attrs.appreciatedByCurrentUser ? appreciated : notAppreciated}" escape="false" />
This is the only thing i can come up with.
<h:panelGroup rendered="#{cc.attrs.appreciatedByCurrentUser}">
<h:outputText value="#{(cc.attrs.count)}" style="display:block;" />
<h:outputText value="#{(cc.attrs.count-1)}" />
</h:panelGroup>
<h:panelGroup rendered="#{not cc.attrs.appreciatedByCurrentUser}">
<h:outputText value="#{(cc.attrs.count+1)}" style="display:block;" />
<h:outputText value="#{(cc.attrs.count)}" />
</h:panelGroup>
Putting <br> in a value attribute will always throw errors in JSF, so you'll have to use display:block.

JSF: ui:include param for "for"-attribute

I have swapped out a composition to re-use it. The composition contains tags like this:
<t:radio for=":someForm:someComponent" index="#{index}" />
I include the composition like this:
<ui:include src="/theComposition.xhtml">
<ui:param name="someParam" value="#{someBean}" />
</ui:include>
But how can I parameterize the "someForm" part of the composition? Because that will differ depending on where I include it. I could pass a string... but how should I concatenate it? Or is there any other way?
You can just inline EL in the attribute value.
<t:radio for=":#{someParam}:someComponent" index="#{index}" />

JSF: logic based on iteration index

Pardon me for the title, that's the best my limited brain can came up this late.
So, i have a list of string, something like [abc, def, ghi].
The question: in JSF, how do I iterate the list and create a string that look like this "abc, def, ghi" (notice the commas)?
For those who have the urge to tell me that I'd better use a Java method to concatenate the string, hear this: every member of the list should be rendered as a separate commandLink.
If plain JSF it would look like:
<h:commandLink>abc</h:commandLink>, <h:commandLink>def</h:commandLink>, <h:commandLink>ghi</h:commandLink>
Assuming that #{bean.items} returns List<String> or String[], in JSF 1.x you can use JSTL c:forEach with varStatus. It gives you a handle to LoopTagStatus which has a isLast() method.
<c:forEach items="#{bean.items}" var="item" varStatus="loop">
<h:commandLink value="#{item}" /><c:if test="#{!loop.last}">, </c:if>
</c:forEach>
In Facelets as shipped with JSF 2.x, same functionality is available by ui:repeat.
<ui:repeat value="#{bean.items}" var="item" varStatus="loop">
<h:commandLink value="#{item}" />#{!loop.last ? ', ' : ''}
</ui:repeat>

Resources