Abordaremos hoje um assunto cada vez mais comum no mundo da web, o AJAX.
Nosso objetivo aqui é adicionar recursos AJAX a um componente JSF customizado, portanto o foco do artigo se encontra na implementação e não nas definições AJAX e JSF, as quais presume-se que você já conheça.
Assim como em qualquer aplicação web, nossa tarefa aqui se resume a realizar uma chamada AJAX no lado do cliente e responder a esta chamada no lado do servidor. Então, o javascript renderizado pelo nosso componente consiste da instanciação do nosso objeto XMLHttpRequest ou ActiveXObject, da realização da chamada e a lógica envolvida no processo.
Instanciando o XMLHttpRequest ou ActiveXObject
var ajaxReq = null;
function getXMLHttpRequest(){
if (ajaxReq==null){
if (window.XMLHttpRequest) {
ajaxReq = new XMLHttpRequest();
} else if (window.ActiveXObject){
try {
ajaxReq = new ActiveXObject(“Msxml2.XMLHTTP.4.0″);
} catch(e) {
try {
ajaxReq = new ActiveXObject(“Msxml2.XMLHTTP.3.0″);
} catch(e) {
try {
ajaxReq = new ActiveXObject(“Msxml2.XMLHTTP”);
} catch(e) {
try {
ajaxReq = new ActiveXObject(“Microsoft.XMLHTTP”);
} catch(e) {
ajaxReq = false;
}
}
}
}
}
}
return ajaxReq;
}
A realização da chamada
function algumaFuncaoSua(){
var parametersName = new Array();
var parametersValue = new Array();// Nomes dos parâmetros
parametersName[0] = “parametroA”;
// Valores dos parâmetros
parametersValue[0] = “valorDeA”;
// Prepara a requisição
req = prepareRequest(parametersName,parametersValue);
// Realiza a requisição
req.request.onreadystatechange = processAjaxResponse;
req.request.send(req.params);
}function prepareRequest(parametersName,parametersValue){
// identificador é um input qualquer para sabermos de qual formulário
// pegar a ação, a qual deve apontar para a própria página
var formAction = document.getElementById(‘identificador’).form.action;
var formName = document.getElementById(‘identificador’).form.id;
var params = “”;
var result = new Array();
var ajax = getXMLHttpRequest();// Inicializa params
params += formName + “=” + formName;
// Monta URL
for (i=0;i<parametersName.length;i++)
params += “&” + parametersName[i] + “=” + parametersValue[i];
// Informa ser ajax
params += “&method=ajax&requestId=” + Math.random();
ajax.open(“POST”,formAction,true);
ajax.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);result.request = ajax;
result.params = params;return result;
}function processAjaxResponse(){
var request = getXMLHttpRequest();if (request.readyState == 4) {
if (request.status == 200){
// Realiza o decode
getDecodedXML(request.responseXML);
// Reseta a requisição ajax
ajaxReq = null;
}
}
}function getDecodedXML(){
// aqui você trata seu XML de acordo com a sua necessidade
alert(responseXML.getElementsByTagName(“resposta”)[0].firstChild.nodeValue);
}
No código acima temos uma função que envia um parâmetro para o nosso componente chamado “parametroA” com valor “valorDeA”.
Sabemos para onde enviar a requisição devido a um campo (input qualquer, hidden por exemplo) que nosso componente adiciona (simplementes imprimindo o HTML na função decode ou ainda renderizando tal campo utilizando alguma tab library). Podemos também afirmar que a identificação de que a requisição é ajax pode ser feita via um parâmetro “method” adicionado a url em prepareRequest.
Agora que já temos o javascript implementado, vamos ao nosso componente.
/**
* Etapa mediana no processo de renderizacao da tela
*
* @param context
* @param component
*/
public void decode(FacesContext context, UIComponent component){
ExternalContext extContext = context.getExternalContext();
// Pegamos os parametros
String ajaxIdVal = (String)
extContext.getRequestParameterMap().get(“method”);
String parametroA = (String)
extContext.getRequestParameterMap().get(“parametroA”);// Define se esta e uma requisicao normal ou ajax
if (null == ajaxIdVal || -1 == ajaxIdVal.indexOf(“ajax”)) {
// Se for normal, adiciona um campo hidden e encerra o decode
writer.startElement(HTML.INPUT_ELEM, component);
writer.writeAttribute(“type”, “hidden”, null);
writer.writeAttribute(“id” , “identificador”, null);
writer.endElement(HTML.INPUT_ELEM);
return;
}/*
* Executa caso seja uma requisicao ajax
*/
// Gera o XML de resposta
HttpServletResponse response = (HttpServletResponse)
context.getExternalContext().getResponse();// Define o tipo de resposta
response.setContentType(“text/xml”);
response.setHeader(“Cache-Control”, “no-cache”);// Imprimimos a resposta em XML
ResponseWriter writer = context.getResponseWriter();
writer.startElement(“resposta”, component);
writer.write(“Aqui a resposta XML”);
writer.startElement(“resposta”, component);// Encerra a resposta
context.responseComplete();
}
Como podemos perceber, pegamos o contexto externo da aplicação e obtemos os valores dos parâmetros, o que nos possibilita identificar o tipo de requisição que está sendo feita e responder de acordo.
No nosso caso, a resposta para uma requisição normal é a geração de um input hidden para identificarmos o formulário que nos possibilita realizar a chamada para a página aonde o componente está inserido, e para uma requisição AJAX a resposta é um XML. Nada nos impede de responder com um HTML, bastaria mudar o content-type da resposta para “text/html”.
Nosso componente agora possui funcionalidades AJAX!
Até a próxima!
Cezar,
estou com a duvida, o qual é a classe extendida que usa ajax?
estou muito necessario isso.
Desde já agradeço.
Opa!
O metodo decode do Renderer sempre é chamado, seja uma requisição Ajax ou não.
Então o método javascript envia um parâmetro “method=ajax”, para que o decode possa saber que se trata de uma chamada Ajax.
Abraço!
Cezar, tentei e nem consegui a requisição via ajax.
no meu codigo de Managed Bean aqui:
public class aluno{
private String nome;
private int idade;
…
get/set
…
decode(FacesContext context){
ExternalContext extContext = Context.getExternalContext();
Collection c = extContext.getRequestParameterMap().values();
Iterator i = c.iterator();
while(i.hasNext()){
System.out.println(i.next().toString());
}
}
}
não saiu imprimir objeto “next()” no console.
JavaScript:
var xmlHTTP = getXMLHttpRequest();
var params = formName+”=”+formName;
params+= “&method=ajax&”+formName+”:”+idInput+”=”+value;
xmlHTTP.open(“POST”,formAction,true);
xmlHTTP.setRequestHeader(“Content-type”,”application/x-www-form-urlencoded”);
xmlHTTP.setRequestHeader(“Content-length”,params.length);
xmlHTTP.onreadystatechange=function(){…….}
xmlHTTP.send(params);
Agradeço.
Decode é um método definido numa classe Renderer, ou seja, não no seu bean.
Dê uma olhada em Criando componentes JSF