I have written a program using jsf 1.2 . In this program a user needs to select his country, state, and city. When he selects a country, he must see the list of states in it in a dropdown & when he selects a state, he must see the cities in it in a dropdown.
For that I have created 2 classes, 1 inner class , and one jsf page.
When I select a country , I can see a dropdown for state is immediately shown.
Problem is when a state is changed, the drop down for city is not immediately seen. Only after 2nd change in state, the drop down for cities is seen.
(Note: I cannot remove the method cityChangeListener()
in this code , as i need to generate an id using country-code,state-code,city-code,and a random number. )
Any help would be highly appreciated.
Here is my code (4 files):
file: faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<managed-bean>
<managed-bean-name>formBackingBean</managed-bean-name>
<managed-bean-class>FormBackingBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope></managed-bean>
</faces-config>
file: newjsf.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<f:view>
<h:form>
<h:inputText
id="input"
value="#{formBackingBean.input}"
immediate="true"
disabled="true"
/>
<br/>
<h:selectOneMenu
id="country"
value="#{formBackingBean.country}"
valueChangeListener="#{formBackingBean.countryChangeListener}"
immediate="true"
onchange="submit();"
>
<f:selectItems
id="countries"
value="#{formBackingBean.countries}"
/>
</h:selectOneMenu>
<br/>
<h:selectOneMenu
id="state"
value="#{formBackingBean.state}"
valueChangeListener="#{formBackingBean.stateChangeListener}"
immediate="true"
onchange="submit();"
rendered="#{formBackingBean.states!=null}"
>
<f:selectItems
id="states"
value="#{formBackingBean.states}"
/>
</h:selectOneMenu>
<br/>
<h:selectOneMenu
id="city"
value="#{formBackingBean.city}"
immediate="true"
onchange="submit();"
rendered="#{formBackingBean.cities!=null}"
valueChangeListener="#{formBackingBean.cityChangeListener}"
>
<f:selectItems
id="cities"
value="#{formBackingBean.cities}"
/>
</h:selectOneMenu>
</h:form>
</f:view>
file: FormBackingBean.java
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
public class FormBackingBean {
private String input;
private String country;
private String state;
private String city;
private List<SelectItem>countries=GeoMapLister.WORLD.getNamesOfPlacesWithin();//MapLister.countryList;
private List<SelectItem>states=null;
private List<SelectItem>cities=null;
public FormBackingBean() {
}
public String getCity() {
return city;
}
public String getCountry() {
return country;
}
public String getState() {
return state;
}
public void setCity(String city) {
this.city = city;
FacesContext.getCurrentInstance().renderResponse();
}
public void setCountry(String country) {
this.country = country;
FacesContext.getCurrentInstance().renderResponse();
}
public void setState(String state) {
this.state = state;
}
public List<SelectItem> getCities() {
return cities;
}
public List<SelectItem> getCountries() {
return countries;
}
public List<SelectItem> getStates() {
return states;
}
public void setCities(List<SelectItem> cities) {
this.cities = cities;
}
public void setCountries(List<SelectItem> countries) {
this.countries = countries;
}
public void setStates(List<SelectItem> states) {
this.states = states;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public void countryChangeListener(final ValueChangeEvent valueChangeEvent){
input=valueChangeEvent.getNewValue().toString();
states=GeoMapLister.WORLD.getPlacesWithin().get(input).getNamesOfPlacesWithin();
state=null;
cities=null;
city=null;
FacesContext.getCurrentInstance().renderResponse();
}
public void stateChangeListener(final ValueChangeEvent valueChangeEvent){
input=valueChangeEvent.getNewValue().toString();
cities=GeoMapLister.WORLD.getPlacesWithin()
.get(country).getPlacesWithin().get(input)
.getNamesOfPlacesWithin();
city=null;
FacesContext.getCurrentInstance().renderResponse();
}
public void cityChangeListener(final ValueChangeEvent valueChangeEvent){
input=valueChangeEvent.getNewValue().toString();
FacesContext.getCurrentInstance().renderResponse();
}
}
file: GeoMapLister.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.faces.model.SelectItem;
public class GeoMapLister {
public static class GeographicalLocation{
private final GeographicalLocation parent;
private final String code;
private final String name;
private final List<SelectItem>namesOfPlacesWithin;
private final HashMap<String,GeographicalLocation>placesWithin;
public GeographicalLocation(GeographicalLocation parent,String code, String name,boolean leaf) {
this.parent = parent;
this.name = name;
this.code= code;
ArrayList<SelectItem> namesofplaceswithin = null;
HashMap<String,GeographicalLocation> placeswithin = null;
if(!leaf){
namesofplaceswithin = new ArrayList<SelectItem>();
namesofplaceswithin.add(new SelectItem(null, "- select -"));
placeswithin = new HashMap<String,GeographicalLocation>();
placeswithin.put(null, null);
}
this.namesOfPlacesWithin = namesofplaceswithin;
this.placesWithin = placeswithin;
}
public String getName() {
return name;
}
public GeographicalLocation getParent() {
return parent;
}
public List<SelectItem> getNamesOfPlacesWithin() {
return namesOfPlacesWithin;
}
public String getCode() {
return code;
}
public GeographicalLocation addPlaceWithin(String code,String name,boolean leaf){
GeographicalLocation newGeographicalLocation = new GeographicalLocation(this, code,name,leaf);
placesWithin.put(code,newGeographicalLocation);
namesOfPlacesWithin.add(new SelectItem(code, name));
return newGeographicalLocation;
}
public HashMap<String, GeographicalLocation> getPlacesWithin() {
return placesWithin;
}
List<SelectItem> getPlacesWithin(String input) {
return placesWithin.get(input).namesOfPlacesWithin;
}
}
public static final GeographicalLocation WORLD=new GeographicalLocation(null, "WORLD","WORLD",false);
static
{
GeographicalLocation IN = WORLD.addPlaceWithin("IN", "India", false);
GeographicalLocation MH = IN.addPlaceWithin("MH", "Maharashtra", false);
MH.addPlaceWithin("MU", "Mumbai", true);
MH.addPlaceWithin("PU", "Pune", true);
MH.addPlaceWithin("NA", "Nashik", true);
GeographicalLocation KA = IN.addPlaceWithin("KA", "Karnataka", false);
KA.addPlaceWithin("BA", "Bangalore", true);
KA.addPlaceWithin("MA", "Mangalore", true);
GeographicalLocation BE = IN.addPlaceWithin("BE", "West Bengal", false);
BE.addPlaceWithin("KO", "Kolkata", true);
BE.addPlaceWithin("KH", "Kharagpur", true);
//--------------
GeographicalLocation UK = WORLD.addPlaceWithin("UK", "U.K.", false);
GeographicalLocation YO = UK.addPlaceWithin("YO", "York", false);
YO.addPlaceWithin("SS", "Sussex", true);
YO.addPlaceWithin("MS", "Middlesex", true);
//--------------
GeographicalLocation US = WORLD.addPlaceWithin("US", "U.S.A.", false);
GeographicalLocation NY = US.addPlaceWithin("NY", "New York", false);
NY.addPlaceWithin("NC", "New York city", true);
NY.addPlaceWithin("NU", "New York urban", true);
GeographicalLocation CA = US.addPlaceWithin("CA", "California", false);
CA.addPlaceWithin("WA", "Washington, district of California", true);
CA.addPlaceWithin("SI", "Silicon Valley", true);
CA.addPlaceWithin("VS", "Very-Silly-Con Valley", true);
}
}