I want to store the selected value of the first attribute managedabean "refCont" in a second attribute of the managed bean and then I'll post. but the value will show that after the second selection knowing that the value displayed is the one selected for the first time. I do not know what's sake
.xhtml
<h:outputText value="* Contact" />
<h:selectOneMenu id="contact" value="#{reclamationMB.refCont}" onchange="lazyload()">
<c:set value="#{reclamationMB.refCont}" target="#{contactMB}" property="refContt" />
<f:ajax listener="#{contactMB.affichReclContact}" />
<f:selectItem itemLabel="Select One" noSelectionOption="true" itemValue="---" />
<f:selectItems value="#{contactMB.contactsClient}" noSelectionValue="" var="contact" itemValue="#{contact.refCont}" itemLabel="#{contact.nomCont}" />
<f:selectItems itemLabel="Autre" itemValue=""></f:selectItems>
</h:selectOneMenu>
first ManagedBean:
#RequestScoped
public class ReclamationMB extends AbstractMB implements Serializable {
private int refCont;//ref contact recuperé pour la creation de la reclamation
.....
//getter and setter
Second Mnaged bean
#RequestScoped
public class ContactMB extends AbstractMB implements Serializable {
#ManagedProperty("#{reclamationMB.refCont}")
private int refContt;
.....
//getter an setter
public void affichReclContact(AjaxBehaviorEvent event){
contact=service.AffichContact(refContt);
setContact(contact);
}
The problem is that JSTL's <c:set> is a view build time tag handler, and not a view render time UI component, so your problem is a classical one: when you expect it to set the value, it is no longer there in the component tree. Moreover, it has run when there was no <h:selectOneMenu> tag at all.
Of course, if <h:selectOneMenu> implemented ActionSource, just like <h:commandButton>, you could have nested JSF <f:setPropertyActionListener> for the reason of setting the bean property with the needed values, as in <f:setPropertyActionListener target="#{contactMB.refContt}" value="#{reclamationMB.refCont}">. But you can't do that.
Basically you can do two things:
Use PrimeFaces <p:remoteCommand> tag, which can hold the abovementioned action listener to set the needed value, and call it in onchange method. There are a bunch of such examples here on Stack Overflow and in excellent PrimeFaces' documentation.
Make use of bean injection, instead of just bean property injection. In the former case, the expression reclamationMB.getRefCont() will always yield the right result in the holder bean, provided that reclamationMB is the variable to hold the injected bean by #ManagedProperty.
Related
This question already has answers here:
How does the 'binding' attribute work in JSF? When and how should it be used?
(2 answers)
Closed 6 years ago.
I have some trouble dealing with PrimeFaces 5.0 and a panelGroup with "binding". I know, "binding" sucks, but I'm working with a legacy system and believe me, it's truly hard to make it the right way, without "binding".
So, when I click mi link, the getter of the "binding" property is called before the "action", then the action is called, and after all the "update". But, the component is not properly updated.
Even if I make it to run the "action" before the getter of the binding, and the getter is returning the right stuff, this particular component is not updated.
I have more components without binding which are updated properly, but not the one with "binding".
UPDATE:
Here is the rest of the code. flag starts with "false" value.
The page always print "READ ONLY".
Somepage.xhtml
<h:form id="frm">
<p:commandLink value="#{messages.Guardar}" id="bt_Guardar" action="#{myBean.flagFalse}" update="someid" />
<p:commandLink value="#{messages.Editar}" id="bt_Editar" action="#{myBean.flagTrue}" update="someid" />
<h:panelGroup id="someid" layout="block">
<h:panelGroup id="panelCamposTD" layout="block" binding="#{myBean.someStuff}" ></h:panelGroup>
</h:panelGroup>
</h:form>
And my myBean, wich is a SessionScoped bean (because it comes from a legacy system)
#ManagedBean(name="myBean")
#SessionScoped
public class MyBean implements Serializable{
private static final long serialVersionUID = 7628440827777833854L;
private boolean flag = false;
public void flagFalse(){
flag = false;
}
public void flagTrue(){
flag = true;
}
public HtmlPanelGroup getSomeStuff(){
HtmlPanelGroup pg = new HtmlPanelGroup();
HtmlOutputText t = new HtmlOutputText();
if (flag){
t.setValue("EDITED");
}else{
t.setValue("READ ONLY");
}
pg.getChildren().add(t);
return pg;
}
public void setSomeStuff(HtmlPanelGroup pg){
return;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
You should avoid bindings to managed beans with session scope. This can cause a lot of touble:
JSF 2.0 Spec
3.1.5 Component Bindings
[...]
Component bindings are often used in conjunction with JavaBeans that are dynamically instantiated via the Managed Bean Creation facility (see Section 5.8.1 “VariableResolver and the Default VariableResolver”). It is strongly recommend that application developers place managed beans that are pointed at by component binding expressions in “request” scope. This is because placing it in session or application scope would require thread-safety, since UIComponent instances depends on running inside of a single thread. There are also potentially negative impacts on memory management when placing a component binding in “session” scope.
There are two solutions which could avoid the binding:
In this solution, the output text is always visible and just get a different text from the backed bean:
<h:panelGroup id="someid" layout="block">
<h:panelGroup id="panelCamposTD" layout="block">
<h:outputText value="#{myBean.flaggedText}"></h:outputText>
</h:panelGroup>
</h:panelGroup>
Add the getter to the backed bean:
public String getFlaggedText(){
if (flag){
return "EDITED";
}else{
return "READ ONLY";
};
}
The other option is to put both output texts in the front end and hide one of them:
<h:panelGroup id="someid" layout="block">
<h:panelGroup id="panelCamposTD" layout="block">
<h:outputText value="EDITED" rendered="#{myBean.flag}"></h:outputText>
<h:outputText value="READ ONLY" rendered="#{not myBean.flag}"></h:outputText>
</h:panelGroup>
</h:panelGroup>
I have a p:commandLink in my xhtml with the value toggling between "Show"/"Hide".
Is there any way by which I can get the value of this commandlink from the backing bean?
I mean, I want to know what value the command link is showing currently i.e. Show/Hide?
To the point, the invoking component is just available in ActionEvent argument:
<h:commandLink id="show" value="Show it" actionListener="#{bean.toggle}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.toggle}" />
with
public void toggle(ActionEvent event) {
UIComponent component = event.getComponent();
String value = (String) component.getAttributes().get("value");
// ...
}
However, this is a poor design. Localizable text should absolutely not be used as part of business logic.
Rather, either hook on component ID:
String id = (String) component.getId();
or pass a method argument (EL 2.2 or JBoss EL required):
<h:commandLink id="show" value="Show it" actionListener="#{bean.toggle(true)}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.toggle(false)}" />
with
public void toggle(boolean show) {
this.show = show;
}
or even just call the setter method directly without the need for an additional action listener method:
<h:commandLink id="show" value="Show it" actionListener="#{bean.setShow(true)}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.setShow(false)}" />
As #BalusC suggested, your approach is not a good solution. But if you really want to do that, you can bind the component (p:commandLink) to your backingbean, as seen in What is the advantages of using binding attribute in JSF?.
After the component was bound, you can access the value attribute from the p:commandLink.
I have written a piece of code to put two pairs of radio button in a *.xhtml page of a JSF project built in JSF2.0, Jboss As 7.1.1 final and JDK 6.0, PrimeFaces 3.4.2.
<h:panelGrid columns="2">
<h:selectOneRadio value="#{calendarBean.radioFirst}">
<f:selectItem id="morning" itemValue="morning" itemLabel="Morning"/>
<f:selectItem id="afternoon" itemValue="afternoon" itemLabel="Afternoon"/>
</h:selectOneRadio>
<h:selectOneRadio style="padding-left: 170px" value="#{calendarBean.radioSecond}">
<f:selectItem id="noon" itemValue="noon" itemLabel="Noon"/>
<f:selectItem id="endofday" itemValue="endofday" itemLabel="End Of Day"/>
</h:selectOneRadio>
</h:panelGrid>
The Bean is:
private String radioFirst="morning";
private String radioSecond="endofday";
public String getRadioFirst() {
return radioFirst;
}
public void setRadioFirst(String radioFirst) {
this.radioFirst = radioFirst;
}
public String getRadioSecond() {
return radioSecond;
}
public void setRadioSecond(String radioSecond) {
this.radioSecond = radioSecond;
}
I have written a method to invoke on a Action Event where I want to have the values of the radio button selected. when the method invokes I get the value of the radio buttons as "morning" and "endofday" as these two are the initial values of the bean variables.
private String radioFirst="morning";
private String radioSecond="endofday";
But if I change the radio button options, I don't get the updated values, its the same old initial values. How can I get the changed values? Please help!
Three things
Don't use the session scope for this usage scenario. This will go completely wrong when your users open the same page in more than one tab. Use request scope or view scope.
Use a regular action instead of an action listener, and don't provide the radio button values as attributes. This makes no sense. The selectOneRadio components will set the updated values on your backing bean. When your action method is invoked, you will have access to those values via the instance fields of your bean.
Leave out the window.reload. If you need a full page refresh after the action, set ajax to false on the p:commandButton or use an h:commandButton.
You should modify your action button like this :
<p:commandButton actionListener="#{userLeaveBean.addAppliedLeave}" styleClass="apply_button" value="Create Leave">
<f:attribute name="userId" value="#{employee.name}"/>
</p:commandButton>
As #MikeBraun suggested, remove the window.reload(). If you want to refresh something, you could do it by using the update attribute from the p:commandButton.
And modify your bean according to this :
#ManagedBean
#SessionScoped // Could probably be moved to #RequestScoped or #ViewScoped
public class UserLeaveBean
{
#ManagedProperty(value="#{calendarBean}")
CalendarBean calendarBean;
public void setCalendarBean(CalendarBean calendarBean)
{
this.calendarBean = calendarBean;
}
public void addAppliedLeave(ActionEvent event)
{
System.out.println("Radio 1 : " + calendarBean.getRadioFirst());
System.out.println("Radio 2 : " + calendarBean.getRadioSecond());
}
}
The ManagedProperty will get the other bean accessible for you by injecting it inside the current one. Use the proper scope, probably you are using SessionScoped because you are using window.reload().
Important : the ManagedProperty bean must be at least scoped the same length as the other bean.
Read more :
Injecting Managed Beans in JSF 2.0
PrimeFaces Showcase - commandButton
What is the difference between setPropertyActionListener vs attribute vs param?
When would use the setPropertyActionListener?
1. f:setPropertyActionListener:
With this tag, you can directly set property in you backing bean. Example:
xhtml:
<h:commandButton action="page.xhtml" value="OK">
<f:setPropertyActionListener target="#{myBean.name}" value="myname"/>
</h:commandButton>
backing bean:
#ManagedBean
#SessionScoped
public class MyBean{
public String name;
public void setName(String name) {
this.name= name;
}
}
This will set name property of backing bean to value myname.
2. f:param:
This tag simple sets the request parameter. Example:
xhtml:
<h:commandButton action="page.xhtml">
<f:param name="myparam" value="myvalue" />
</h:commandButton>
so you can get this parameter in backing bean:
FacesContext.getExternalContext().getRequestParameterMap().get("myparam")
3. f:attribute:
With this tag you can pass attribute so you can grab that attribute from action listener method of your backing bean.
xhtml:
<h:commandButton action="page.xhtml" actionListener="#{myBean.doSomething}">
<f:attribute name="myattribute" value="myvalue" />
</h:commandButton>
so you can get this attribute from action listener method:
public void doSomething(ActionEvent event){
String myattr = (String)event.getComponent().getAttributes().get("myattribute");
}
You should use f:setPropertyActionListener whenever you want to set property of the backing bean. If you want to pass parameter to backing bean consider f:param and f:attribute. Also, it is important to know that with f:param you can just pass String values, and with f:attribute you can pass objects.
we are still in a JSF 1.2 to 2.0 migration scenario and we are now facing a problem related to c:set or ui:param variables used inside an EL expression.
Here are the facts. There is a button as composite component:
<cc:interface name="button" shortDescription="A button.">
...
<cc:attribute
name="disabled"
required="false"
default="false"
shortDescription="The disabled flag." />
...
</cc:interface>
<cc:implementation>
<ice:commandButton
...
disabled="#{cc.attrs.disabled}"
... />
</cc:implementation>
Now we are trying to use this button component inside a toolbar. The disabled state of the button is determined inside the toolbar using a c:set or a ui:param (we already tried both ways).
<c:set var="isButtonEnabled" value="#{backingBean.buttonEnabled}" />
or
<ui:param name="isButtonEnabled" value="#{backingBean.buttonEnabled}" />
#{isButtonEnabled}
<ctrl:button
...
disabled="#{!isButtonEnabled}"
... />
So here is our problem. If we simple print out the value of "isButtonEnabled" in the toolbar, it is always correct. So the backing bean is ok. But when we try to pass this value to the composite component, it is not working. "Disabled" is always evaluated to false.
Sure we could pass the method expression directly (#{!backingBean.isButtonEnabled}) and this will work fine. But in our scenario the determination of the enabled-flag is much more complicated and I just tried to keep the example as simple as possible. Aditionally this flag is used for multiple buttons inside the toolbar, so we wanted to keep the code maintainable by using a c:set or ui:param. Is this the wrong way to handle this? What do you recommend?
Thanks in advance.
SlimShady
Your problem is the way value binding is done in JSF. The prefered way is to retrieve the EL Expression an attribute was populated with by invoking getValueExpression("attributeName"). Then this EL Expression can be used to get or set the value in the backing bean. As your not passing #{!isButtonEnabled} but #{cc.attrs.disabled} to ice:commandButton the binding fails.
I solved this for the p:selectOneMenu component of Primefaces by writing a wrapping UIComponent which defines a property wrappedValue and passed that property to the p:selectOneMenu. In the getter and setter of that property I then used getValueExpression to retieve the real EL Expression for the attribute.
<composite:interface componentType="de.gw2tome.component.valuewrapper">
<composite:attribute name="value" type="de.gw2tome.models.Rarity"
required="true" />
</composite:interface>
<composite:implementation>
<p:selectOneMenu value="#{cc.wrappedValue}"/>
...
</composite:implementation>
#FacesComponent("de.gw2tome.component.valuewrapper")
public class ValueWrapper extends UINamingContainer {
public void setWrappedValue(Object wrappedValue) {
ValueExpression expr = getValueExpression("value");
ELContext ctx = getFacesContext().getELContext();
expr.setValue(ctx, wrappedValue);
}
public Object getWrappedValue() {
ValueExpression expr = getValueExpression("value");
ELContext ctx = getFacesContext().getELContext();
return expr.getValue(ctx);
}
}
The component can now be used the following way:
<g:rarityChooser value="#{itemSearchBean.minRarity}" />