String concatenation in EL for dynamic ResourceBundle key - jsf

I have a resource bundle with entries like these:
entry1=value1
entry2=value2
entry3=value3
In my JSF page I'm trying to use these keys dynamically. The ID of the entry is coming from a managed bean. I think it should be something like this:
<h:outputText value="#{msg['entry' managedBean.entryIndex]}"/>
How can I achieve this?

If you're already on Servlet 3.1 / EL 3.0 (Tomcat 8, WildFly 8, GlassFish 4, etc), make use of new EL 3.0 += operator:
<h:outputText value="#{msg['entry' += managedBean.entryIndex]}" />
If you're only on Servlet 3.0 / EL 2.2 (Tomcat 7, JBoss AS 6/7, GlassFish 3, etc), make use of new EL 2.2 ability to directly invoke methods such as String#concat():
<h:outputText value="#{msg['entry'.concat(managedBean.entryIndex)]}" />
If you're even not on Servlet 3.0 / EL 2.2 yet, make use of <c:set> to create another variable with the desired EL expression inlined:
<c:set var="key" value="entry#{managedBean.entryIndex}" />
<h:outputText value="#{msg[key]}" />

This should solve your issue:
<h:outputText value="#{msg['entry'.concat(managedBean.entryIndex)]}"/>

Here's what worked for me : concat outside of []
<h:outputText value="#{msg['entry'].concat(managedBean.entryIndex)}" />

I think you'll have to write a facelets function concat(str1, str2).

Related

Send array list via ui:param to JSF ui:composition template

I know i can use ui:param to pass a string from a composition built upon a template
Like this: http://www.mkyong.com/jsf2/how-to-pass-parameters-to-jsf-2-0-template-file/
Then I can use the parameter in the XHTML for the template file.
Can you send an array?
I.e.
<ui:insert name="header" >
<ui:include src="/template/common/commonHeader.xhtml">
<ui:array name="tagArray" values="val1, val2, val3" />
</ui:include>
</ui:insert>
Only if your environment supports EL 3.0 (Tomcat 8, WildFly 8, GlassFish 4, etc and newer). You can the use the new list notation #{[x,y,z]}.
<ui:array name="tagList" values="#{['val1', 'val2', 'val3']}" />
If you're not on EL 3.0 yet, then your best bet is using JSTL fn:split() to split a delimited string to an array.
<ui:param name="tagArray" value="#{fn:split('val1,val2,val3', ',')}" />

How to pass a method argument to getter?

I want to use a datalist
<rich:dataList value="#{bean.itemsOnLevel}" var="item">
<h:outputText value="#{item.value}" />
</rich:dataList>
but my getter needs a parameter
public List getItemsOnLevel(int level);
how can I pass the level?
If you're already targeting a Servlet 3.0 compatible container (Tomcat 7, Glassfish 3, JBoss 6, etc) with a Servlet 3.0 compatible web.xml in your webapp, then you can make use of the new EL 2.2 feature of invoking methods with arguments:
<rich:dataList value="#{bean.getItemsOnLevel(1)}" var="item">
<h:outputText value="#{item.value}" />
</rich:dataList>
If you're however targeting an older Servlet 2.5 compatible container (Tomcat 6, Glassfish 2, JBoss 4/5, etc), then your best bet is to install JBoss EL to achieve the same. See also this answer for details: Invoke direct methods or methods with arguments / variables / parameters in EL

How to display value of List#size() in JSF EL?

I'd like to know if there's a way to bind the returned value of a method into a JSF component.
I'll explain myself better.
Let's say I have a class like this:
public class Document {
private List<Attachment> attachments;
//getter and setter here
}
this class is exposed to jsf through a registered managed bean in a property called currentDocument, and used in a jsf this way
<h:outputText value="#{myManagedBean.currentDocument.attachment.size}" />
This isn't correct, I know. But what is the correct way to do this?
Am I supposed to create an attribute on the Document class, let's say numberOfAttachments, and bind to that, or there's a way to bind directly on a method's return value?
If you're running an EL 2.2 capable container (Tomcat 7, Glassfish 3, JBoss AS 6 or newer, all implementing Servlet 3.0), or are using JBoss EL, then you should be able to invoke non-getter methods by EL:
<h:outputText value="#{myManagedBean.currentDocument.attachment.size()}" />
An alternative is to use JSTL fn:length():
<html xmlns:fn="http://java.sun.com/jsp/jstl/functions" ...>
...
<h:outputText value="#{fn:length(myManagedBean.currentDocument.attachment)}" />
If none of that is possible for you for some reason, then your best bet is to create an EL function yourself
<h:outputText value="#{my:size(myManagedBean.currentDocument.attachment)}" />
or to add an extra getter method to #{myManagedBean} which returns exactly that.
<h:outputText value="#{myManagedBean.currentDocumentAttachmentSize}" />
See also:
Invoke direct methods or methods with arguments / variables / parameters in EL

Basic JSF: is it possible to SET a property value in EL?

I need to do something like this:
<a4j:support even="onclick" action="#{myBean.myProperty = null}"/>
I would like to know if this is possible and which would be the proper syntax if so.
If you're running an EL 2.2 capable container (Tomcat 7, Glassfish 3, JBoss AS 6, etc and newer, with a web.xml declared conform at least Servlet 3.0), or are using JBoss EL (your seam tag suggests that you are using it...), then you should be able to invoke methods with arguments in EL:
<a4j:support event="onclick" action="#{myBean.setMyProperty(null)}"/>
An alternative is using <f:setPropertyActionListener>, this is supported in JSF 1.2 as well:
<a4j:support event="onclick" />
<f:setPropertyActionListener target="#{myBean.myProperty}" value="#{null}" />
Bean setter methods are called on form submission but based on your example why not do something like:
<a4j:support event="onclick" action="#{myBean.resetMyProperty}"/>
And in your bean your resetMyProperty method would set the myProperty to null

JSF: Bean method call with parameter

I can't get method calls with parameters to work in JSF 2.0 (MyFaces) and Tomcat 6.
This is how I try it:
<f:selectItems var="item" value="#{bla.someList}
itemValue="#{item.value1}"
itemLabel="#{item.value2}">
<f:param name="param1" value="0" />
</f:selectItems>
I can't define the method like this, right? And why not?
getSomeList(int a)
So this is what I tried:
getSomeList() {
Integer a = Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("param1"));
return doSomething(a);
}
And this is what I get:
java.lang.NumberFormatException: null
java.lang.Integer.parseInt(Integer.java:417)
I would be very grateful if someone helped me out. Thanks!
UPDATE: Ah, it worked with #{bla.getSomeList(0)}!
I can't define the method like this, right?
getSomeList(int a)
No.
And why not?
Because you're using old Tomcat 6 which doesn't support EL 2.2 where this feature was introduced.
And this is what I get:
java.lang.NumberFormatException: null
java.lang.Integer.parseInt(Integer.java:417)
Because there it is null. The <f:param> works in links/buttons only, not on plain components.
In order to get method calls in EL to work, you need to upgrade to a Servlet 3.0 / EL 2.2 capable container like Tomcat 7, or to replace Tomcat 6's default EL 2.1 implementation by one which supports parameterized method calls. For detail see this answer. Once done that, you can use
<f:selectItems value="#{bla.getSomeList(0)}" ... />
An alternative is to replace List by Map, which can be a custom implementation which does (lazy) loading on get() method.
public Map<String, List<Something>> getSomeMap() {
return someCustomLazyLoadingMap;
}
with
<f:selectItems value="#{bla.someMap.keyName}" ... />
Try using
<f:selectItems var="item" value="#{bla.someList(0)} itemValue="#{item.value1}" itemLabel="#{item.value2}"/>
This works for some implementations of JSF.

Resources