[RESOLVIDO] Ajax + Render: não recupera valor input

2 respostas
Alys

Bom dia pessoal,

Tenho um formulário no qual a seleção de uma opção define quais campos estarão visíveis para preenchimento. Estou utilizando ajax. O código está da seguinte forma:

index.xhtml

<h:form>
	<h:panelGrid columns="2" border="0" style="height:200px;">
		<h:panelGroup>
			<h:selectOneRadio value="#{usuarioBean.opcaoDesejada}" layout="pageDirection">  
				<f:selectItem itemValue="#{usuarioBean.opcao1}" itemLabel="Opção 1" />  
				<f:selectItem itemValue="#{usuarioBean.opcao2}" itemLabel="Opção 2"/>  
				<f:selectItem itemValue="#{usuarioBean.opcao3}" itemLabel="Opção 3"/>
				<f:selectItem itemValue="#{usuarioBean.opcao4}" itemLabel="Opção 4"/>
				<f:ajax render="panel" listener="#{usuarioBean.opcaoSelecionada}" />    
			</h:selectOneRadio> 
			<br /><br /><br />
		</h:panelGroup>
		
		<h:panelGroup id="panel" style="margin-left:50px; vertical-align: top;">
				
				<h:panelGroup rendered="#{usuarioBean.codigoVisivel}">
					<h:outputText value="ID:" /><br />
					<h:inputText value="#{usuarioBean.codigo}" />
				</h:panelGroup>
				
				<h:panelGroup rendered="#{usuarioBean.inscricaoVisivel}">
					<h:outputText value="Inscrição:" /><br />
					<h:inputText value="#{usuarioBean.inscricao}" />
				</h:panelGroup>
				...
				
		</h:panelGroup>
	</h:panelGrid>

	<h:commandLink action="#{usuarioBean.pesquisar}"  >
		<h:graphicImage style="border:0px;" alt="Pesquisar" value="/resources/pesquisar.jpg"  />
	</h:commandLink>
</h:form>

O Ajax funciona normalmente. Só que, no UsuarioBean, sempre que envio o formulário (clico no link Pesquisar), os valores dos campos (codigo e inscricao) estão vindo nulos. O problema está relacinado à visibilidade, creio, pois, se eu forço no bean, por exemplo, o valor do campo usuarioBean.codigoVisivel sempre como true, ele recupera o valor digitado normalmente.

Meu UsuarioBean está com escopo Request, o que significa que a cada requisição ajax um novo objeto é criado. Eu testei mudar o escopo para View, nesse cenário o problema é que perco os valores quando navego para a próxima página (após enviar a requisição dessa página, vou para outra de listagem).

@ManagedBean
@RequestScoped
public class UsuarioBean implements Serializable {
	
	private String codigo;
	private String inscricao;
	
	private boolean codigoVisivel;
	private boolean inscricaoVisivel;
	
	public String pesquisar(){
		System.out.println("Chamada para pequisa");
		return "listaUsuarios";
	}
	
	public void opcaoSelecionada(AjaxBehaviorEvent event) {
		//seta visibilidade de acordo com a opção
	}
	
	//getters e setters
}

Gostaria ao máximo evitar colocar o bean com escopo sessão. Alguém tem alguma idéia?

Obrigada.

2 Respostas

Hebert_Coelho
  1. Onde usuarioBean.codigoVisivel é utilizado?
  2. implements Serializable, pq? Se é RequestScoped não precisa.
  3. Com RequestScoped você irá perder igual ao ViewScoped. Não entendi pq o RequestScoped nesse seu caso é melhor que o ViewScoped.
Alys

Oh, gente, sei que tem tempos que abri este tópico, mas, as coisas estão tão corridas que esqueci de voltar aqui.

Apenas para fechar o tópico: consegui resolver o problema.

Antes de explicar como resolvi meu impasse, vou responder aos questionamentos do jakefrog

  1. É utilizado no index.xhtml, na linha 16, para controlar a visibilidade do painel. O mesmo vale para usuarioBean.inscricaoVisivel (linha 21).

  2. Estava com implements Serializable porque meu teste anterior foi com escopo sessão, e esqueci de retirar :oops:

  3. Na realidade, eu não escolhi um melhor, apenas fiz testes com diferentes escopos. Se eu declaro meu Managed Bean com escopo Request, a cada nova requisição um novo objeto UsuarioBean é criado. Isto também vale para requisições via Ajax. Com escopo View, independente de quantas requisições eu faça, enquanto eu permanecer na mesma página, somente um objeto UsuarioBean é criado. Uma forma sismples de confirmar isso é verificando as chamadas ao construtor com cada escopo. Mas, como disse, quando eu mudo de página, um novo objeto é criado, logo perco os dados anteriores. Meu problema era achar um cenário onde isso não ocorresse.

Agora, à solução:

Honestamente, após muita pesquisa, não vi uma forma de funcionamento de listas (minhas telas exigem coisas como paginação, seleção de linhas por checkbox, etc) sem que as mesmas estejam na sessão (inclusive essa foi a recomendação de um arquiteto aqui: mudar para SessionScope). Um artigo que me ajudou a pensar em uma solução foi este: JSF Best Practices - Scope management for clean sessions. Mas, como minha segunda tela possuia muitas manipulações com listas, eventualmente eu caía de novo no problema de perda de dados.

O que fiz no final foi criar dois beans diferentes:

  • o ListaUsuarioBean, com escopo Sessão, que armazena somente as listas de dados que preciso (meu bean/pojo usuário possui uma sublista de dependentes e outra com algumas características), e tem somente os Getters e Setters para recuperar estas listas (seria a mesma coisa que recuperar o objeto Session e setar o mapa de atributos direto, mas acho assim mais elegante - ou menos gambiarrado :wink: );

  • o UsuarioBean, escopo View, com os demais dados, incluindo estes booleans para controlar quais paineis aparecem na tela, e os métodos de ação (pesquisar, selecionar, deletar, etc).

Não é uma solução das mais elegantes, fato. Mas, ao menos limitou a quantidade de dados salvos na sessão e, o prazo estava vencendo, não deu para pesquisar outras alternativas =(

Criado 24 de fevereiro de 2012
Ultima resposta 7 de mar. de 2012
Respostas 2
Participantes 2