JSF Exemplos Simples com Ajax

Olá, tudo bem?

Hoje vamos exibir alguns simples modos de fazer chamadas Ajax utilizando JSF 2.0.

Para ver outros posts sobre Web Applications/JSF basta acessar os links a seguir: JSF Exibindo Objeto e Mensagens após Redirect, Validação de Login de Usuário com JSF e JAASJSF: Converter and Bean AutoCompleteJSF – Hello World, AutoComplete, Tratando Exceções em uma Aplicação Web, Autenticação de Usuários (Filter/Servlet), Criando um WebServer.

Ao final do post de hoje você verá o código para download. No post (Validação de Login de Usuário com JSF e JAAS) é exibido como instalar o JBoss 6 caso você queira executar o código do post de hoje. Você precisará instalar o JBoss Tools em seu Eclipse.

Veja a tela abaixo e seu respectivo código.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
	<h:form>
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}"/>
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!"/>
		<br />
	</h:form>
</h:body>
</html>

Como exibir o nome digitado na mesma tela utilizando Ajax? Fácil, basta adicionar o comando “f:ajax” na linha e pronto. Veja a alteração e o resultado na página:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
	<h:form>
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}"/>
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName" execute="inputname" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
	</h:form>
</h:body>
</html>

Viu como é simples? Passei apenas o valor que será levado,  para o ManagedBean, através do parâmetro “execute” e quem eu gostaria que o JSF atualizasse através do parâmetro “render”.

Repare que o nome digitado aparece no console também.

Esse exemplo serve para atualizar todos os tipos de componentes. Vamos para mais um?

Vamos fazer com que uma mensagem de erro seja exibida caso o nome preenchido tenha menos que 4 letras.

Veja o novo código da página e a mensagem exibida:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
	<h:form>
		<h:messages id="myMessage" globalOnly="true" showDetail="true"/>
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}"/>
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName myMessage" execute="inputname" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
	</h:form>
</h:body>
</html>
package demo;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String name;

	public String sayHello() {
		if (isNameIncorrect()) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Too small", "Can you write it a little bigger?"));
		}

		System.out.println(name);
		return null;
	}

	private boolean isNameIncorrect() {
		return "".equals(name.trim()) || name.length() < 3;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Note no código que foi colocado um “h:messages” e ele tem seu ID utilizado pelo componente “f:ajax”.  Essa solução também funciona quando você tem um componente do tipo “h:message for=”YYY””.

Vamos trabalhar agora com comboboxes? Iremos exibir um combobox que contenha no máximo 4 itens quando temos um nome com menos de 6 caracteres ou uma lista com mais de 4 itens quando temos um nome com mais de 6 caracteres:

package demo;

import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UISelectItems;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String name;

	private List<String> cars;

	private String selectedCar;
	private HtmlSelectOneMenu htmlSelectCars;

	private static final String SELECT_A_CAR = "Select One Car";

	public User() {
		cars = new ArrayList<String>();
	}

	public String sayHello() {
		if (isNameInCorrect()) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Too small", "Can you write it a little bigger?"));
		}

		System.out.println(name);
		return null;
	}

	private boolean isNameInCorrect() {
		return name == null || "".equals(name.trim()) || name.length() < 3;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void editMyCarsList(AjaxBehaviorEvent event) {
		if (htmlSelectCars == null) {
			htmlSelectCars = new HtmlSelectOneMenu();
		}

		htmlSelectCars.getChildren().clear();

		UISelectItems items = new UISelectItems();
		items.setValue(getCars());
		htmlSelectCars.getChildren().add(items);
	}

	public List<String> getCars() {
		cars.clear();

		cars.add(SELECT_A_CAR);

		if (!isNameInCorrect() && name.length() >= 6) {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
			cars.add("Passat");
			cars.add("Vectra");
			cars.add("Chevet");
			cars.add("Corvet");
		} else {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
		}

		return cars;
	}

	public void setCars(List<String> cars) {
		this.cars = cars;
	}

	public String getSelectedCar() {
		return selectedCar;
	}

	public void setSelectedCar(String selectedCar) {
		this.selectedCar = selectedCar;
	}

	public HtmlSelectOneMenu getHtmlSelectCars() {
		editMyCarsList(null);

		return htmlSelectCars;
	}

	public void setHtmlSelectCars(HtmlSelectOneMenu htmlSelectCars) {
		this.htmlSelectCars = htmlSelectCars;
	}
}

Repare agora nosso código na página:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
	<h:form>
		<h:messages id="myMessage" globalOnly="true" showDetail="true" />
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}" />
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName myCars myMessage" execute="inputname" listener="#{user.editMyCarsList}" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
		<br />
		<br />
		Choose your car: <h:selectOneMenu id="myCars" binding="#{user.htmlSelectCars}" value="#{user.selectedCar}" />
		<br />
		<br />
	</h:form>
</h:body>
</html>

Como você pode perceber no código acima, o combobox tem seu valor alterado de acordo com o nome digitado. Ao final do post, irei explicar por que utilizei o binding ao componente HtmlSelectOneMenu ao invés de passar uma lista (List<String>) diretamente.

Como último exemplo, vamos fazer com que tenha um combobox invisível que só apareça quando o usuário tiver selecionado algum carro.

Veja como ficar nosso ManagedBean:

package demo;

import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UISelectItems;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String name;

	private List<String> cars;
	private List<String> colors;

	private String selectedCar;
	private String selectedColor;
	private HtmlSelectOneMenu htmlSelectCars;

	private static final String SELECT_A_CAR = "Select One Car";

	public User() {
		cars = new ArrayList<String>();
		colors = new ArrayList<String>();

		colors.add("Red");
		colors.add("Blue");
		colors.add("Orange");
		colors.add("Pink --> O.o");
	}

	public String sayHello() {
		if (isNameInCorrect()) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Too small", "Can you write it a little bigger?"));
		}

		System.out.println(name);
		return null;
	}

	private boolean isNameInCorrect() {
		return name == null || "".equals(name.trim()) || name.length() < 3;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void editMyCarsList(AjaxBehaviorEvent event) {
		if (htmlSelectCars == null) {
			htmlSelectCars = new HtmlSelectOneMenu();
		}

		htmlSelectCars.getChildren().clear();

		UISelectItems items = new UISelectItems();
		items.setValue(getCars());
		htmlSelectCars.getChildren().add(items);
	}

	public List<String> getCars() {
		cars.clear();

		cars.add(SELECT_A_CAR);

		if (!isNameInCorrect() && name.length() >= 6) {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
			cars.add("Passat");
			cars.add("Vectra");
			cars.add("Chevet");
			cars.add("Corvet");
		} else {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
		}

		return cars;
	}

	public void setCars(List<String> cars) {
		this.cars = cars;
	}

	public String getSelectedCar() {
		return selectedCar;
	}

	public void setSelectedCar(String selectedCar) {
		this.selectedCar = selectedCar;
	}

	public List<String> getColors() {
		return colors;
	}

	public void setColors(List<String> colors) {
		this.colors = colors;
	}

	public boolean isColorsAlloweToDisplay() {
		if (isNameInCorrect()) {
			return false;
		}

		if (selectedCar == null || selectedCar.trim().equals("") || selectedCar.equals(SELECT_A_CAR)) {
			return false;
		}

		return true;
	}

	public String getSelectedColor() {
		return selectedColor;
	}

	public void setSelectedColor(String selectedColor) {
		this.selectedColor = selectedColor;
	}

	public HtmlSelectOneMenu getHtmlSelectCars() {
		editMyCarsList(null);

		return htmlSelectCars;
	}

	public void setHtmlSelectCars(HtmlSelectOneMenu htmlSelectCars) {
		this.htmlSelectCars = htmlSelectCars;
	}
}

Repare que foram alterações bem simples, onde adicionamos um List um método que irá dizer quando a lista deve ser exibida ou não.

Veja como ficou nossa página:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
	<h:form>
		<h:messages id="myMessage" globalOnly="true" showDetail="true" />
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}" />
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName myCars myMessage myColors" execute="inputname" listener="#{user.editMyCarsList}" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
		<br />
		<br />
		Choose your car:
		<h:selectOneMenu id="myCars" binding="#{user.htmlSelectCars}" value="#{user.selectedCar}">
			<f:ajax render="myColors" execute="inputname myCars"/>
		</h:selectOneMenu>
		<br />
		<br />
		<h:panelGroup id="myColors">
			<h:selectOneMenu value="#{user.selectedColor}" rendered="#{user.colorsAlloweToDisplay}">
				<f:selectItems value="#{user.colors}" />
			</h:selectOneMenu>
		</h:panelGroup>
	</h:form>
	</h:body>
</html>

Agora farei diversas observações sobre o código e práticas adotadas:

  • HtmlSelectOneMenu – Eu utilizei o componente ao invés de uma simples lista por um pequeno detalhe. O JSF ainda não se dá bem na hora de construir os objetos na tela (DOM Tree). Com isso, se a primeira lista tinha 4 itens e depois, via ajax, você adiciona mais itens ele não irá reconhecer os itens mais novos. Com isso mesmo com uma lista contendo um novo valor o JSF não irá reconhecer, e você irá apenas poder utilizar os valores antigos. Você pode tentar com List<String> ao invés do component HtmlSelectOneMenu apenas e ver o que vai acontecer, fiquei umas 3~4 horas de pesquisa para achar uma solução.
  • HtmlSelectOneMenu dentro do “h:panelGroup” – Adicionei o selectOne dentro do panelGroup pois toda vez que um objeto não é exibido e você deseja exibi-lo é necessário atualizar todo seu container. Ou seja, se o segundo selectOne (cores) estivesse no mesmo “form”, você deveria utilizar seu “render” em todo o form.

Click Aqui para fazer o download do código do programa de hoje.

Espero que o post de hoje possa te ajuda.

Qualquer dúvida/pergunta/comentário poste abaixo.

Até a próxima

20 thoughts on “JSF Exemplos Simples com Ajax

    • Olá Carlos, boa noite.

      Atualmente existe o curso da Caelum e o professor Carlos Ribeiro que eu sempre ouvi falar bem.

      Tem também a Infnet mas segundo me falaram depende do professor que você pega.

      Isso para o RJ, caso você more em outro estado, a Caelum está presente em outros lugares.

      Att,

    • Olá Paulo, bom dia.

      Penso sim em começar uma sessão sobre JMS. Antes, preciso terminar minha pós e tirar a certificação EJB.

      Obrigado pela visita.

  1. Cara solucionou muitas dúvidas minhas, parábens e muito obrigado!
    Quando eu estiver bom mesmo em java, vou fazer um site para postar dicas e soluções também.

    Valeu!

  2. Olá meu caro, você está de parabens está passando o teu conhecimento para os demais, inclusive a min e está sendo muito útil, porem, recentemente tenho enfrentado um problema com o ajax que nao estou conseguindo resolver, gostaria de saber se voce ja passou por algo semelhante e se poderia me ajudar, o problema é o seguinte:

    Possuo uma pagina de cadastro de pacientes em jsf com alguns campos obrigatórios, nessa pagina eu faço a verificação atraves da data de nascimento se o paciente é menor de idade, caso ele seja, passo a ser obrigado a cadastrar os dados do responsavel pelo menor, ou seja, na pagina aparecem todos os campos necessario para o cadastro do paciente maior de idade, quando eu seto uma data de nascimento que retorna um menor de idade a pagina é renderizada através da tag

    Up!

    e a pagina renderiza os dados obrigatorios do responsavel pelo paciente, até o momento estava tudo bem, o problema surge quando eu tento salvar o paciente menor de idade sem que todos os campos obrigatórios estejam preenchidos, pois ele retorna as mensagens informando que os campos faltam ser preenchido, ao mesmo tempo que a mensagem aparece a renderização de responsavel feita pelo ajax morre e some da tela de cadastro e so volta depois que clico no campo data de nascimento (paciente) e saiu do input ai a pagina é renderizada novamente com os dados do responsavel.

    Alguem saberia me explicar como resolver esse problema, pois ja tentei de varias formas
    agora estava tentando com a anotação

     @ViewScoped 

    , porem possuo a

    @ManegedProperty(value="#{paciente}")

    Não sei se fui bem claro quanto ao meu problema, mais qualquer coisa so perguntar que tento esclarecer mais

    `@ManagedBean`
    `@RequestScoped`
    `public class PacienteBean implements Serializable {`

    ` private static final long serialVersionUID = 9004155295461993935L;`

    ` @ManagedProperty(value =”#{paciente}”)`
    ` private Paciente paciente;`

    ` private List listaPaciente;`

    ` public String save(){`
    ` try {`

    Grato
    Rafael Wandeson

    • Rafael, boa tarde.

      Infelizmente não tenho como ajudar nisso agora.

      JSF depende de análise e análise de código, pequenos detalhes fazem muita diferença.

      Poste sua dúvida no GUJ para que alguém que tenha tempo hábil possa te ajudar.

      Até mais.

  3. Primeiramente Parabens pelo post.
    A possibilidade de aplicar o modelo usado no metodo “editMyCarsList” em combox de EstadoCidades?
    Falo isso pq usariamos o ajax semelhante ao usado nas listas de carro.
    Ou nao funcionaria?

    • Alexandre, boa noite.

      O Primefaces tem seu próprio comportamento para esse tipo de ação.

      Te aconselho a ver no site do Primefaces exemplo de utilização de Ajax dele.

      Por padrão, todo request do Primefaces era Ajax então nem precisaria dessa tag para disparar o ajax.

      Até mais.

Leave a Comment