JSF SelectOneMenu Dependente

1 resposta
A

Vou tentar explicar meu problema atual.

Consegui fazer com que ao selecionar uma opção no primeiro SelectOneMenu o segundo seja carregado com as informações pertinentes a escolha do primeiro. Quando eu escolho pela primeira vez a opção no primeiro SelectOneMenu, a escolha seguinte não funciona como esperado e assim começa um ciclo de alternâncias de funcionamento e não-funcionamento do elemento.

Veja o vídeo em anexo (Flash), creio que com ele dê para entender bem o problema na prática. Prestem atenção nos valores que aparecem em Contrato e o logo abaixo do botão Cadastrar. O primeiro é setado na primeira linha do método getTodosSistemas e o segundo no final da página, ambos listados abaixo.

Alguem pode me esclarecer o erro que estou cometendo ou até mesmo um exemplo detalhado de como fazer essa dependência, apenas com JSF?

Obrigado!

Anexos

Código da Página
<h:selectOneMenu id="regional" value="#{ConsumidorBean.idRegional}" onchange="submit()" immediate="false">  
   <f:selectItems value="#{RegionalBean.todosParaComboBox}" />  
</h:selectOneMenu>  

<h:selectOneMenu id="sistema" value="#{ConsumidorBean.consumidor.sistema.id}">  
   <f:selectItems value="#{ConsumidorBean.todosSistemas}" />  
</h:selectOneMenu>  
.  
.  
.  
<h:outputText value="#{ConsumidorBean.idRegional}" />
Código do Bean
public class ConsumidorBean {  
  private Consumidor consumidor = new Consumidor();  
  private GerenciadorConsumidor gerenciador;  
  private int idRegional;  
  private DataModel model;  
  private String mensagem;  
  
  public ConsumidorBean() throws Exception{  
	gerenciador = new GerenciadorConsumidor();  
	consumidor.setCentroCusto(new CentroCusto());  
	consumidor.setTipoConsumidor(new TipoConsumidor());  
	consumidor.setSistema(new Sistema());  
  }  
.  
.  
.	 
  public List getTodosSistemas() throws Exception{  
	consumidor.setNumContrato(Integer.toString(idRegional));  
	List sistemasJsf = new ArrayList();  
	List<Sistema> sistemas = new GerenciadorSistema().retornarSistema(idRegional);  
	for (Sistema elem : sistemas) {  
	  String id = Integer.toString(elem.getId());  
	  sistemasJsf.add(new SelectItem(id, elem.getDescricao()));  
	}  
	return sistemasJsf;  
  }  
.  
.  
.  
}

Vídeo do Problema na Prática

1 Resposta

A

Aleluia consegui fazer o que queria. Segue uma breve explicação de como fiz para ter meus SelectOneMenu dependetes.

Eu tenho a página JSP com o seguinte código.

<h:selectOneMenu id="regional" valueChangeListener="#{ConsumidorBean.regionalChanged}" onchange="submit()">
   <f:selectItems value="#{RegionalBean.todosParaComboBox}" />
</h:selectOneMenu>

<h:selectOneMenu id="sistema" value="#{ConsumidorBean.consumidor.sistema.id}">
   <f:selectItems value="#{ConsumidorBean.todosSistemas}" />
</h:selectOneMenu>

No atributo valueChangeListener da Tag SelectOneMenu eu vinculei o método regionalChanged do meu Bean Consumidor. Isso quer dizer que este método vai ser chamado sempre que o SelectOneMenu tiver o seu valor modificado.

No atributo onchange eu coloquei a instrução submit() para que o formulário seja enviado e ele seja reprocessado. Acho que esta parte é bem clara para todos.

Agora vamos para o Bean

public void regionalChanged(ValueChangeEvent event){
   idRegional = Integer.parseInt((String) event.getNewValue());
}

A assinatura deste método deve ser como está acima: do tipo void e com um parâmetro do tipo ValueChangeEvent. O método getNewValue() retorna um Object ai você tem que fazer os casts como precisar. No meu caso eu preciso de um Inteiro.

:?: Mas porque você não colocou diretamente o cast para Inteiro: idRegional = (Integer) event.getNewValue() :?:

Pelos meus testes eu entendi que mesmo o retorno do método getNewValue() sendo um Object, verdadeiramente o valor é do tipo String. Então eu precisei fazer como fiz. Na verdade eu percebi isso com a mensagem de erro quando tentei usar apenas o cast pra Integer, não sei explicar perfeitamente este detalhe. Se alguém que tenha conhecimento puder contribuir, será de grande valia para todos.

Bem, está ai o mínimo que se precisa para capturar o valor de um SelectOneMenu para popular outro dependente deste.

Para deixar mais claro o funcionamento vou postar o código do método que popula o SelectOneMenu de id sistema.

public List getTodosSistemas() throws Exception{
   List sistemasJsf = new ArrayList();
   List<Sistema> sistemas = new GerenciadorSistema().retornarSistema(idRegional);
   for (Sistema elem : sistemas) {
      String id = Integer.toString(elem.getId());
      sistemasJsf.add(new SelectItem(id, elem.getDescricao()));
   }
   return sistemasJsf;
}

Neste método getTodosSistemas faço uso da propriedade idRegional na terceira linha, cuja recebeu o valor do SelectOneMenu que disparou o método regionalChanged.

Acho que é isso. Nada de avançado demais, mas funcional.
Comentários são bem vindos, principalmente aqueles que mencionarem cuidados, alertas e possíveis problemas com essa implementação.

Obrigado!

Criado 26 de junho de 2008
Ultima resposta 26 de jun. de 2008
Respostas 1
Participantes 1