Pessoal, eu também consegui fazer funcionar com dois dropdowns dependentes, mas e quando for preciso trabalhar com mais niveis?
Quero montar a seguinte situação Pais, Estado e Cidade.
Até o Pais e Estado, tudo bem, funciona. Mas quando eu seleciono o Estado o valor do dropdown não é setado no ManagerBean. Criei um Converter seguindo o exemplo do Rafael Ponte, mesmo assim não funcionou, vejam:
<h:form>
<h:panelGrid id="panel" rendered="true" border="0" columns="2" width="500" cellpadding="1" cellspacing="2">
<h:outputLabel value="Pais" for="pais"/>
<h:selectOneMenu id="pais"
value="#{umb.pessoa.pais.id_pais}"
rendered="true">
<f:selectItems value="#{umb.paises}"/>
<a4j:support event="onchange"
ajaxSingle="true"
action="#{umb.actionCarregarEstados}"
reRender="estado"/>
</h:selectOneMenu>
<h:outputLabel value="Estado" for="estado"/>
<h:selectOneMenu id="estado"
value="#{umb.pessoa.estado.id_estado}"
rendered="true">
<f:selectItems value="#{umb.estados}"/>
<f:converter converterId="estadoConvert"/>
<a4j:support event="onchange"
ajaxSingle="true"
action="#{umb.actionCarregarCidades}"
reRender="cidade"/>
</h:selectOneMenu>
<h:outputLabel value="Cidade" for="cidade"/>
<h:selectOneMenu id="cidade"
value="#{umb.pessoa.cidade.id_cidade}"
rendered="true">
<f:selectItems value="#{umb.cidades}"/>
</h:selectOneMenu>
</h:panelGrid>
</h:form>
O manager Bean:
public class UirapuruManagerBean {
private RegiaoDAO regiaoDao = null;
private Pessoa pessoa = new Pessoa();
private SelectItem[] estados;
private SelectItem[] cidades;
public UirapuruManagerBean(){
this.regiaoDao = new RegiaoDAO();
this.estados = new SelectItem[1];
estados[0] = new SelectItem("0","Escolha seu Estado");
this.cidades = new SelectItem[1];
cidades[0] = new SelectItem("0","Escolha sua Cidade");
}
/**
* Obtem todos os registros de paises e transformá-os em um
* array de itens do tipo interpretado pelo JSF.
* @return Array de SelectItem do Faces
*/
public SelectItem[] getPaises(){
List<Pais> lp = regiaoDao.getAllPais();
List<SelectItem> itens = new ArrayList<SelectItem>(lp.size());
for( Pais p : lp ){
itens.add( new SelectItem(p.getId_pais(), p.getNm_pais()) );
}// for end
return itens.toArray( new SelectItem[itens.size()] );
}
/**
* Obtem todos os registros de estados relacionados ao páis informado e
* transformá-os em um array de itens do tipo interpretado pelo JSF.
* @param Identificação do Pais
* @return Array de SelectItem do Faces
*/
public SelectItem[] getEstadosByPais(int id_pais){
List<Estado> estados = regiaoDao.getEstadosDoPais(id_pais);
List<SelectItem> itens = new ArrayList<SelectItem>(estados.size());
for( Estado e : estados ){
itens.add( new SelectItem(e.getId_estado(), e.getNm_estado()) );
}// for end
return itens.toArray( new SelectItem[itens.size()] );
}
/**
*
* @param Identificação do Estado
* @return Array de SelectItem com as Cidades
*/
public SelectItem[] getCidadesByEstado(int id_estado){
System.out.println("ID-Estado: " + id_estado);
List<Cidade> cidades = regiaoDao.getCidadesDoEstado(id_estado);
List<SelectItem> itens = new ArrayList<SelectItem>(cidades.size());
for( Cidade c : cidades ){
itens.add( new SelectItem(c.getId_cidade(), c.getNm_cidade()) );
}// for end
return itens.toArray( new SelectItem[itens.size()] );
}
/**
*
* @return
*/
public String actionCarregarEstados(){
this.estados = getEstadosByPais( getPessoa().getPais().getId_pais() );
return "SUCCESS";
}
/**
*
* @return
*/
public String actionCarregarCidades(){
this.cidades = getCidadesByEstado( getPessoa().getEstado().getId_estado() );
return "SUCCESS";
}
public SelectItem[] getEstados() {
return estados;
}
public void setEstados(SelectItem[] estados) {
this.estados = estados;
}
public Pessoa getPessoa() {
return pessoa;
}
public void setPessoa(Pessoa pessoa) {
this.pessoa = pessoa;
}
public SelectItem[] getCidades() {
return cidades;
}
public void setCidades(SelectItem[] cidades) {
this.cidades = cidades;
}
}
Vou colocar o converter aqui, por que acredito que o problema seja nele! Eu fiz seguindo a dica do Rafael Ponte - http://www.rponte.com.br/2008/07/26/entity-converters-pra-da-e-vender/
public class EstadoConvert implements Converter{
/*
* @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
*/
public Object getAsObject( FacesContext arg0, UIComponent component, String valor ){
SelectItem selectedItem = this.getSelectedItemByIndex(component, Integer.parseInt(valor));
if( selectedItem != null )
return selectedItem.getValue();
return null;
}
protected SelectItem getSelectedItemByIndex( UIComponent component, int index ){
List<SelectItem> items = this.getSelectItems(component);
int size = items.size();
if( index > -1 && size > index ){
return items.get(index);
}
return null;
}
protected List<SelectItem> getSelectItems( UIComponent component ){
List<SelectItem> items = new ArrayList<SelectItem>();
int childCount = component.getChildCount();
if( childCount == 0 )
return items;
List<UIComponent> children = component.getChildren();
for( UIComponent child : children ){
if( child instanceof UISelectItem ){
this.addSelectItem((UISelectItem) child, items);
}else if( child instanceof UISelectItems ){
this.addSelectItems((UISelectItems) child, items);
}
}
return items;
}
protected void addSelectItem( UISelectItem uiItem, List<SelectItem> items ){
boolean isRendered = uiItem.isRendered();
if( !isRendered ){
items.add(null);
return;
}
Object value = uiItem.getValue();
SelectItem item;
if( value instanceof SelectItem ){
item = (SelectItem) value;
}else{
Object itemValue = uiItem.getItemValue();
String itemLabel = uiItem.getItemLabel();
// JSF throws a null pointer exception for null values and labels,
// which is a serious problem at design-time.
item = new SelectItem(itemValue == null ? "" : itemValue,
itemLabel == null ? "" : itemLabel, uiItem.getItemDescription(), uiItem.isItemDisabled());
}
items.add(item);
}
@SuppressWarnings("unchecked")
protected void addSelectItems( UISelectItems uiItems, List<SelectItem> items ){
boolean isRendered = uiItems.isRendered();
if( !isRendered ){
items.add(null);
return;
}
Object value = uiItems.getValue();
if( value instanceof SelectItem ){
items.add((SelectItem) value);
}else if( value instanceof Object[] ){
Object[] array = (Object[]) value;
for( int i = 0; i < array.length; i++ ){
// TODO test - this section is untested
if( array[i] instanceof SelectItemGroup ){
resolveAndAddItems((SelectItemGroup) array[i], items);
}else{
items.add((SelectItem) array[i]);
}
}
}else if( value instanceof Collection ){
Iterator<SelectItem> iter = ((Collection<SelectItem>) value).iterator();
SelectItem item;
while( iter.hasNext() ){
item = iter.next();
if( item instanceof SelectItemGroup ){
resolveAndAddItems((SelectItemGroup) item, items);
}else{
items.add(item);
}
}
}else if( value instanceof Map ){
for( Map.Entry<Object, Object> entry : ((Map<Object, Object>) value).entrySet() ){
Object label = entry.getKey();
SelectItem item = new SelectItem(entry.getValue(),
label == null ? (String) null : label.toString());
// TODO test - this section is untested
if( item instanceof SelectItemGroup ){
resolveAndAddItems((SelectItemGroup) item, items);
}else{
items.add(item);
}
}
}
}
protected void resolveAndAddItems( SelectItemGroup group, List<SelectItem> items ){
for( SelectItem item : group.getSelectItems() ){
if( item instanceof SelectItemGroup ){
resolveAndAddItems((SelectItemGroup) item, items);
}else{
items.add(item);
}
}
}
/*
* @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
*/
public String getAsString( FacesContext arg0, UIComponent arg1, Object obj ){
String key = "0";
if( obj instanceof Integer ){
key = String.valueOf( obj );
}
return key;
}
}
Alguém pode me ajudar, por favor?
Valeu!