Osama Al-Haj Hassan
Osama Al-Haj Hassan

Reputation: 65

Value of <h:selectBooleanCheckbox> is not updated according to backing bean value

I'm using JSF2 and Tomcat server. I programmed a simple example in which:

Everything works fine for "h:inputText". On the other hand, the value of "h:selectBooleanCheckBox" does not change. Why is this happening?

By the way, the use of boolean value inside a HashMap is intentional because the project I'm working on has lots of boolean values in a HashMap. So, replacing the Hashmap with a simple boolean property and using a getter and a setter for it is definitely not a solution for my case.

The code for the xhtml page is below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
     <head>       
        <title>Dummy Title</title>        
     </head>    
     <body>
        <h:form>
            <label for="faculty">Faculty</label>
            <h:selectOneMenu id="faculty" value="#{test.selectedFaculty}" converter="faccon" valueChangeListener="#{test.facultyChange}" onchange="submit()">
                <f:selectItems value="#{start.app.faculties}"/>                      
            </h:selectOneMenu>                                  
            <h:selectBooleanCheckbox id="mycheck" value="#{test.x.get(0)}"></h:selectBooleanCheckbox>
            <h:outputText value="#{test.res}"></h:outputText>
            <h:commandButton value="Save" action="#{test.saveChoices}" />
        </h:form>           
    </body>
</html>

The code for the backing bean is below

import java.io.Serializable;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ValueChangeEvent;
import com.myWork.Application;
import com.myWork.Faculty;

@ManagedBean(name="test")
@RequestScoped
public class TestBean implements Serializable
{
    private HashMap<Integer,Boolean> x;
    private String res;
    private Faculty selectedFaculty;

    @PostConstruct
    public void init(){
        Application app = Application.getInstance();
        selectedFaculty = app.getFaculties()[0];
        x = new HashMap<Integer, Boolean>();
        if (selectedFaculty.getFacultyNo()%2==0)
        {
            x.put(0, true);
            res = "even";
        }
        else
        {
            x.put(0, false);
            res = "odd";
        }
    }

    public HashMap<Integer,Boolean> getX() {
        return x;
    }


    public void setX(HashMap<Integer,Boolean> x) {
        this.x = x;
    }

    public Faculty getSelectedFaculty() {
        return selectedFaculty;
    }

    public void setSelectedFaculty(Faculty selectedFaculty) {
        this.selectedFaculty = selectedFaculty;
    }   

    public String getRes() {
        return res;
    }

    public void setRes(String res) {
        this.res = res;
    }

    public void facultyChange(ValueChangeEvent e){
        Faculty fac = (Faculty) e.getNewValue();
        if (fac.getFacultyNo()%2==0)
        {           
            x.put(0, true);
            res = "even";
        }
        else
        {
            x.put(0, false);
            res = "odd";
        }
    }   

    public String saveChoices(){        
        return "test";
    }
}

Any help is greatly appreciated.

Upvotes: 2

Views: 3780

Answers (2)

Jalal Kiswani
Jalal Kiswani

Reputation: 755

Actually your problem is not related to JSF, it is related to EL. in your case, EL treat you map keys as long not int, so you should change your map to be:

HashMap<Long, Boolean> map = new HashMap<>();

and set the key values as follows :

    map.put(0L, false);
    map.put(1L, true);

to force it to be auto-boxed to long.

Note: the problem described in detailed in the following question : EL access a map value by Integer key

Upvotes: 3

Akash Mishra
Akash Mishra

Reputation: 712

In order to send updates to a different component, you can make use of partial page rendering by making Ajax calls to send parameters to Managed bean. Within <h:selectBooleanCheckBox>

 <h:selectOneMenu id="faculty" value="#{test.selectedFaculty}" converter="faccon" valueChangeListener="#{test.facultyChange}">
                <f:selectItems value="#{start.app.faculties}"/>                      
   </h:selectOneMenu>   

  <h:selectBooleanCheckbox id="mycheck" valueChangeListener="#{test.facultyChange}" value="#{test.x.get(0)}">
           <f:ajax event="change" execute="@form" render="faculty"/>
    </h:selectBooleanCheckbox>

Edit: Removed call to onSubmit() in selectOneMenu. introduced an ajax call in selectBooleanCheckbox for partial page refresh. Refer full solution at this post.

Upvotes: 2

Related Questions