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

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

Related

How to implement <f:setPropertyActionListener> programmatically

Basically i'm trying to set a dynamic columns for a <p:datatable>.
The content of one of my columns is a p:commandLink which used to show a dialog for text editing, i have this working like a charm in the XHTML but I need to translate it to Java for dynamic user customization and preferences.
here is what is my XHTML version:
<p:commandLink id="MRepShowButton" update=":form1:display" onclick="EditorDialog.show();" title="Editer le compte rendu">
<f:setPropertyActionListener value="#{exam}" target="#{examenListBean.selectedExamen}" />
</p:commandLink>
and this is my Java version(not working):
CommandLink rapstatelink = (CommandLink)application.createComponent(CommandLink.COMPONENT_TYPE);
rapstatelink.setId("MRepShowButton");
rapstatelink.setUpdate(":form1:display");
rapstatelink.setOnclick("EditorDialog.show();");
rapstatelink.setTitle("Editer le rapport du patient");
ValueExpression target = ef.createValueExpression(elc, "#{exam}", Object.class);
ValueExpression value = ef.createValueExpression(elc, "#{examenListBean.selectedExamen}", Object.class);
//rapstatelink.setActionListener(new SetPropertyActionListenerHandler(**i don't know wht to do here **));
column.getChildren().add(rapstatelink);
table.getChildren().add(column);
You need UICommand#addActionListener(), not UICommand#setActionListener(). The setActionListener() is a deprecated method from JSF 1.x which effectively does a <p:commandLink actionListener="..."> with a ValueBinding.
As to creating the <f:setPropertyActionListener> programmatically, there's unfortunately no JSF implementation independent way for that. Choose either of the following options:
Use the JSF implementation specific class, in case of Mojarra that's the com.sun.faces.taglib.jsf_core.SetPropertyActionListenerImpl:
link.addActionListener(new SetPropertyActionListenerImpl(target, value));
In case of MyFaces that's the org.apache.myfaces.event.SetPropertyActionListener:
link.addActionListener(new SetPropertyActionListener(target, value));
Keep in mind that using JSF implementation specific classes com.sun.faces.* or org.apache.myfaces.* in your own code is a poor practice.
Create a custom ActionListener implementation which does the job. Basically, just copypaste the class' source code from either Mojarra or MyFaces source code into your package. As compared to 1) this has the advantage that your web application does not break when deployed to a Java EE container which ships with the other JSF implementation bundled.
Make use of EL 2.2 feature of the ability to pass method arguments in EL expressions. Then you can just do the job in action or actionListener attribute:
link.setActionExpression(ef.createMethodExpression(elc,
"#{examenListBean.setSelectedExamen(exam)}", Void.class, Exam.class));
(the Exam.class should represent the type of #{exam})
This does effectively the same as
<p:commandLink ... action="#{examenListBean.setSelectedExamen(exam)}" />
Or if you really need to set an action listener:
link.addActionListener(new MethodExpressionActionListener(ef.createMethodExpression(elc,
"#{examenListBean.setSelectedExamen(exam)}", Void.class, Exam.class)));
This does effectively the same as
<p:commandLink ... actionListener="#{examenListBean.setSelectedExamen(exam)}" />

Calling bean methods with arguments from JSF pages

Is it possible to call bean methods & directly pass parameters to them from the view instead of requiring to first set the bean properties and then call methods without arguments using the commandButton or similar ?
I have a list of items with each item having a list of actions. To reduce the state, I am using a single primefaces remoteCommand, in place of several commandButton(s). On getting a action trigger from the view, I would call the remoteCommand from javascript but since the remoteCommand is one but used for multiple items thus I need to pass the id of the item as well. I am wondering if there is a way to pass the id of the item to the bean method directly as an argument instead of first setting it as a bean property ? Is there any way to do so ?
Actually I am looking at a better way to deal with multiple commandButtons on a page when there's a long list of items on the page.
Suggestions ? Thanks.
Using JSF 2.1.6 Mojarra with Primefaces 3.0RC1
Passing method arguments is supported since EL 2.2 which is part of Servlet 3.0. So if your webapp runs on a Servlet 3.0 compatible container (Tomcat 7, Glassfish 3, etc) with a web.xml declared conform Servlet 3.0 spec (which is likely true as you're using JSF 2.1 which in turn implicitly requires Servlet 3.0), then you will be able to pass method arguments to bean action methods in the following form:
<h:commandButton value="Submit" action="#{bean.submit(item.id)}" />
with
public void submit(Long id) {
// ...
}
You can even pass fullworthy objects along like as:
<h:commandButton value="Submit" action="#{bean.submit(item)}" />
with
public void submit(Item item) {
// ...
}
If you were targeting a Servlet 2.5 container, then you could achieve the same by replacing the EL implementation by for example JBoss EL which supports the same construct. See also Invoke direct methods or methods with arguments / variables / parameters in EL.
Yes, it is.
<h:commandButton action="#{bean.method(object)}" />
See this http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/
You can call ManagedBean methods with arguments like this.
<h:commandButton actionListener="#{stateBean.delete(row.stateID)}"
value="Delete" id="btnDeleteS">
<f:ajax event="action" execute="#form" render="#form"/>
</h:commandButton>
The corresponding ManagedBean would be like this.
#ManagedBean
#RequestScoped
public class StateBean
{
#EJB
private RemoteInterface obj=null;
public void delete(String stateID)
{
//Code stuff here.
}
}
You can also directly set the value of ManagedBean properties using <f:setPropertyActionListener></f:setPropertyActionListener> like this.
<h:commandButton value="Delete" id="btnDeleteS">
<f:setPropertyActionListener target="#{stateBean.someProperty}"
value="#{someValue}"/>
<f:ajax event="action" execute="#form" render="#form"/>
</h:commandButton>

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

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.

String concatenation in EL for dynamic ResourceBundle key

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).

Resources