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
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 simple CDI bean. The problem is that when I invoke method removeCustomer from the JSF page, method getCustomers() is executed before removeCustomer instead the opposite way. First I thought that producer itself is the problem but I'm getting same behavior if I put the list inside the controller. When I get response page the row in the table is not removed ether it is removed from the database. When I refresh page once more I don't see the deleted row.
#Named
#RequestScoped
public class CustomersController {
#Inject
private CustomerService customerService;
#Produces()
#RequestScoped
#Named("customers")
public List<Customer> getCustomers() {
return customerService.findCustomers();
}
/**
* #param customerId
*/
public String removeCustomer(Long customerId) {
customerService.deleteCustomer(customerId);
return null;
}
}
<h:form id="customers-form">
<h:dataTable value="#{customers}" var="customer"
styleClass="table">
<h:column>
<f:facet name="header">#{msg['customer.name']}</f:facet>
#{customer.name}
</h:column>
<h:column>
<f:facet name="header">#{msg['customer.vat']}</f:facet>
#{customer.vat}
</h:column>
<h:column>
#{msg['global.edit']}
</h:column>
<h:column>
<h:commandButton styleClass="btn btn-danger"
action="#{customersController.removeCustomer(customer.id)}"
value="#{msg['global.delete']}" aria-hidden="true">
<f:ajax render="#form"></f:ajax>
</h:commandButton>
</h:column>
</h:dataTable>
I'm using JBoss WildFly beta 1 but I'm guessing that it uses stable JSF 2.x version.
Check this answer
The method getCostumers is called before because the EL expresion (#customers) is being evaluated several times while processing the request (more details in the link).
The solution is to make your getters and setters "dumb". Just make them change a variable of your class. Avoid logic with side effects (like customerService.findCustomers();). If you need initialization, you can perform it in a #PostConstruct method or in a method fired by a JSF event).
Also, take into account that with a #RequestScoped bean, a new instance of the bean will be created for every request (either to render the page, or to save changes to the values).
Actually it is pretty easy to achieve what I want.
Here is updated CDI bean.
#Named
#RequestScoped
public class CustomersController {
#Inject
private CustomerService customerService;
#Inject
private List<Customer> customers;
#Produces()
#RequestScoped
#Named("customers")
public List<Customer> getCustomers() {
return customerService.findCustomers();
}
/**
* #param customerId
*/
public void removeCustomer(Customer customer) {
customerService.deleteCustomer(customer.getId());
customers.remove(customer);
}
}
As you can see. On ajax request to remove the customer producer is invoked before method removeCustomer. Logically because in restore view phase jsf is restoring view and evaluating EL expressions and this is happening before event processing phase. So we have list of customers in request scope and we need to inject it in controller bean so we can remove from the list selected customer in the removeCustomer method. I hope I was clear enough.
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.
I am new to jsf 2.0 and therefore i am facing a serious issue grouping the prime faces datagrid and radio buttons. I am using JSF 2.0-Primefaces 3.3, java 1.6, and running my application on tomcat server on windows operating system.
The issue is grouping data grid and radio button. The following paragraph will describe about an example code:
#ManagedBean(name="quickBill")
#ViewScoped
public class QuickBill extends BaseManagedBean implements Serializable {
private List<String[]> insurerIDs=null;
#PostConstruct
public void init(){
loadInsurer();
}
private void loadInsurer(){
logger.info("Entered Load Insurer");
insurerIDs = new ArrayList<String[]>();
if (null != insurerList) {
insurerIDs.add(new String[] {"InsurerID1","Insurer_Name1") });
insurerIDs.add(new String[] {"InsurerID2","Insurer_Name2") });
insurerIDs.add(new String[] {"InsurerID3","Insurer_Name3") });
insurerIDs.add(new String[] {"InsurerID4","Insurer_Name4") });
}
}
public List<String[]> getinsurerIDs() {
return insurerIDs;
}
}
The jsf code is as follows:
<p:dataGrid var="quickBillVar" value="#{quickBill.insurerIDs}" columns="4" >
<p:column selectionMode="single">
<p:selectOneRadio id="options" value="#{quickBill.selectedOption}">
<f:selectItem itemLabel="#{quickBillVar[1]}" itemValue="#{quickBillVar[1]}"/>
</p:selectOneRadio>
<p:commandLink id="insurerid" title="Isurer">
<p:graphicImage value="../../images/insurers1/#{quickBillVar[0]}.jpg"/>
</p:commandLink>
</p:column>
</p:dataGrid>
The above code when executed results in the display of the radio button, which allows user to select multiple radio button at the same time. However the requirement is to restrict user to select only one button rather than allowing user to select multiple button at a time. I have also used selectionMode="single" to produce the expected output but it didn't help much.
Kindly help me on this or provide me with examples which will overcome this issue.
I believe the custom layout in this example will help.
https://www.primefaces.org/showcase/ui/input/oneRadio.xhtml
You can try the below code using Map.
Backing bean code
String selectedInsurer;
Map<String,String> insurerIDs = new LinkedHashMap<String,String>();
insurerIDs.put("InsurerID1", "Insurer_Name1"); //(label, value)
insurerIDs.put("InsurerID2", "Insurer_Name2");
insurerIDs.put("InsurerID3", "Insurer_Name3");
insurerIDs.put("InsurerID4", "Insurer_Name4");
//-- getter & setter
At front end
<h:selectOneRadio value="#{quickBill.selectedInsurer}">
<f:selectItems value="#{quickBill.insurerIDs}" />
</h:selectOneRadio>
I'm new to JSF and I want to spend a text when an action is executed successfully. But the output text, it is not when the action is executed successfully.
Here is the view (deactivatePerson.xhtml):
<h:outputText value="#{msg.personIsDeactivate}" rendered="#{isPersonDeactivate}" />
<h:form>
<h:commandButton action="#{controller.deactivate}" value="#{msg.deactivate}" />
</h:form>
Here is the managed bean:
#ManagedBean
#SessionScoped
public class Controller {
private boolean isPersonDeactivate = false;
public String deactivate() {
isPersonDeactivate = false; // Deactivate process...
isPersonDeactivate = true;
return "persondeactivate";
}
//Getter and Setter
}
Here is the faces-config.xml:
<navigation-rule>
<navigation-case>
<from-outcome>persondeactivate</from-outcome>
<to-view-id>/deactivatePerson.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Can someone please tell me what I do wrong here?
You forgot to reference it as a property of the #{controller} managed bean. It's unclear what your getter look like, but boolean properties should have a getter prefixed with is instead of get. The property name itself should preferably not have an is prefix. It should rather be a verb statement.
Thus, more so:
private boolean personDeactivated;
public boolean isPersonDeactivated() {
return personDeactivated;
}
Then you can reference it as follows:
<h:outputText ... rendered="#{controller.personDeactivated}" />
Unrelated to the concrete problem, navigation cases are superfluous since the new JSF 2.0 implicit navigation. Just let your action method return "deactivatePerson" and it'll go to the proper view without needing a <navigation-case>. Make sure that you're reading proper JSF 2.x targeted resources and not JSF 1.x targeted ones.