Combos - JSF, RichFaces + Ajax

14 respostas
L

Pessoal, boa tarde

Preciso da ajuda de vocês.
Estou fazendo um projeto que preciso atender a seguinte situação.

Tenho o ano, marca e modelo do veículo.
Tenho um combo para cada um.
Os modelos de veículos disponíveis dependem da marca e do ano do veículo que eu escolhi nos combos anteriores.
Se eu ainda não escolhi uma marca, o combo de modelos do veículo não pode exibir nada.

O comportamento dos combos deve ser o seguinte:

Toda vez que eu modifico o ano do veículo, o combo de marcas e de modelos, devem ser renderizados, ou seja, devem ser limpos.

Na primeira vez que entro na aplicação e escolho o ano, tudo funciona perfeitamente.
Mas depois disso, quando eu modifico o ano do veículo, o combo da marca e do modelo continuam populados, ou seja, eles precisariam ser limpos.

Acredito que estou quase lá, está faltando algum detalhe que não consigo descobrir.

Segue abaixo o código da minha página e logo após do Bean:

<h:outputText value="Ano do Veículo" />
			<h:selectOneMenu id="ano" value="#{perfilHandler.perfil.veiculo.ano}">
				<f:selectItems value="#{perfilHandler.listaDeAnos}" />
				<a4j:support event="onchange" action="#{perfilHandler.popularMarcas}"
					ajaxSingle="true" reRender="marca"/>
			</h:selectOneMenu>

			<h:outputText value="Marca" />
			<h:selectOneMenu id="marca"
				value="#{perfilHandler.perfil.veiculo.marca}">
				<f:selectItems value="#{perfilHandler.listaDeMarcas}" />
				<a4j:support event="onchange"
					action="#{perfilHandler.popularModelos}" ajaxSingle="true"
					reRender="modelo" />
			</h:selectOneMenu>


			<h:outputText value="Modelo" />
			<h:selectOneMenu id="modelo"
				value="#{perfilHandler.perfil.veiculo.modelo}">
				<f:selectItems value="#{perfilHandler.listaDeModelos}" />
			</h:selectOneMenu>

Fonte do bean:

public void popularMarcas() {

		listaDeMarcas = new ArrayList();

		Collection marcas = new MarcaVeiculoMock().obterTodasMarcasVeiculo();
		Iterator it = marcas.iterator();
		while (it.hasNext()) {
			MarcaVeiculoVO vo = (MarcaVeiculoVO) it.next();
			SelectItem item = new SelectItem(vo.getCodigoMarca(), vo
					.getNomeMarca());
			listaDeMarcas.add(item);
		}

	}

public void popularModelos() {

		listaDeModelos = new ArrayList();

		Collection modelos = new ModeloVeiculoMock().obterModelosPorAnoMarca(
				perfil.getVeiculo().getMarca(), perfil.getVeiculo().getAno());

		Iterator it = modelos.iterator();

		while (it.hasNext()) {
			ModeloVeiculoVO vo = (ModeloVeiculoVO) it.next();
			SelectItem item = new SelectItem(vo.getCodigoModelo(), vo
					.getNomeModelo());
			listaDeModelos.add(item);
		}

	}

Obrigado pela atenção de todos.

Lucas

14 Respostas

L

E aí pessoal, alguém tem alguma idéia ? :roll: :cry:

J

parece certo… unica coisa que vejo que falta é ao selecionar o ano limpar a lista de modelos e reRenderizar a combo de modelos

vanilton.coelho

Eu achava que os metodos chamados pela tag do richfaces e que executariam alguma ação, necessariamente deveriam ter receber como parametro um ActionEvent, não é necessário??? estou com um problema que o 1º combo gera o 2º, até ai tudo bem, mas o 2º deveria gerar o 3º e 4º e não gera nem a pau, oque pode ser??? debugei e nem entra no método para geração do 3º e 4º, gostaria de uma luz do que poderia ser.

vanilton.coelho

agora no meu caso não tem o ajaxSingle não, seria para???

rponte

Utilizem algum componente de escopo conversacional, algo como o t:saveState do Tomahawk ou o rich:keepAlive (ou é a4j:keepAlive) do Richfaces para manter as listas durante as requisições.

Abraços e boa sorte.

vanilton.coelho

achava que nao precisava disso utilizando ajax. será que isso está influenciando o meu caso??? devo dar um save state no value ou aonde ??? percebi aqui no debug que o segundo combo para gerar o 3º e 4º nem chama o metodo do 2º combo, porque será?

rponte

Olá,

Trabalhando com Richfaces ou não você ainda terá que cuidar do escopo conversacional dos teus managed beans, o AJAX funciona sobre o ciclo de vida, isto é, o ciclo não é alterado numa requisição AJAX. Só para efeitos de teste: coloque teu managed bean com escopo de session e tente rodar novamente.

Abraços e boa sorte.

vanilton.coelho

vou tentar. Valeu a força.

vanilton.coelho

realmente isso resolveu, mas a página não é para estar na sessao, então como eu resolvo, em quais caras eu coloco saveState??? eu tenho

vários List<SelectItem> mas acredito que não precise
cada combo é populado em um DTO no meu Bean, tipo meuBean.meuDTO.id, e ai??? salvo oq???

rponte

realmente isso resolveu, mas a página não é para estar na sessao, então como eu resolvo, em quais caras eu coloco saveState??? eu tenho
vários List<SelectItem> mas acredito que não precise
cada combo é populado em um DTO no meu Bean, tipo meuBean.meuDTO.id, e ai??? salvo oq???

Na verdade não é sua página que fica em escopo session, mas sim teus managed beans. Onde colocar o t:saveState? Depende, mas coloque o t:saveState para cada lista do teu managed bean, deve resolver :slight_smile:

vanilton.coelho

Cara, estranho eu ter que dar o saveState na lista, porque oque o managed bean precisa é o valor selecionado na lista, que no caso está sendo mapeado em algum Dto, o saveState nao deve ficar nesse cara???

quando ao escopo, eu já sabia que era do managed bean e nao da pagina.

rponte

Seu managed bean está em escopo de request, logo a cada requisição seu m.bean é instanciado e provavelmente uma das listas de objetos se perde nesse momento, e quando chega na fase de validação/conversão o componente não consegue mais obter a mesma lista de objetos construida inicialmente, logo ocorre o problema.

O que você precisa manter são as listas, e não os valores, pois os valores serão setados no m.bean a cada request se não houver erro de validação.
Abraços.

vanilton.coelho

valeu cara, vou testar assim entao.

CURIOSO_GYN

Brother, estou com um probleminha parecido com o seu e gostaria de saber se vc já resolveu?? Olha só, tenho uma tabela de cadastro de Cidades(codigo, nome, uf), e uma outra tabela de Clientes(codigo, nome, endereço, bairro, cidade, uf). A tabela cliente está vinculada a tabela cidade, ou seja, quando faço um cadastro de cliente tem-se uma Combo Cidade que me lista todas as cidades cadastradas da tabela Cidade. A questão é, que quero que ao escolher a cidade nessa Combo da tabela Cliente, o campo estado(inputText) assuma o estado no qual a cidade faz parte. Ex.: se escolher Goiânia na Combo, que no inputText do estado apareça GO. Estou tentando utilizar ajax com reRender mas não está me respondendo nada… vou postar o trecho do meu JSF:

[color=red]Trecho do JSF[/color]

<h:outputText value="#{msg_aplic.prt_Cliente_cidade}"/>

<h:panelGroup>

<h:selectOneMenu styleClass=“campos” id=“cidade” required=“true” immediate=“true” value="#     {ClienteControle.cliente.cidade.id}">

<a4j:support event=“onchange” action="#{ClienteControle.obterEstado}" ajaxSingle=“true”  reRender=“estado”/>

<f:selectItem itemLabel="—Escolha a Cidade—" itemValue=""/>

<f:selectItems value="#{ClienteControle.cidadeEstadoCombo}"/>

</h:selectOneMenu>

</h:panelGroup>

h:outputText styleClass=“tituloCampos” value="#{msg_aplic.prt_Cliente_estado}"/>

<h:panelGroup>

<h:inputText required=“true” id=“estado” size=“4” maxlength=“2” readonly=“true”  styleClass=“camposObrigatorios” value="#{ClienteControle.cliente.estado}" rendered="#{ClienteControle.obtertEstado}"/>

<h:message for=“estado” styleClass=“mensagemDetalhada”/>

</h:panelGroup>

[color=red]No meu bean, ficaria mais ou menos assim:[/color]

public void obterEstado(){

.

.

String teste = GO;

.

.

}

[color=blue]Eu executando a aplicação, ao alterar minha Combo para qualquer cidade, no meu campo estado naum deveria aparecer GO???[/color]

Obrigado pela Atenção, fico no aguardo da resposta!

Criado 9 de julho de 2008
Ultima resposta 24 de jan. de 2009
Respostas 14
Participantes 5