[Logo] Mentawai Forum - Mentawai Web Framework
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 

Forum Read-Only! Check the new site and forum here!

33) MentaAjax: Framework em JS do Mentawai para trabalhar facilmente com Ajax no client-side!  XML
Forum Index -> F.A.Q.
Author Message
robertwgil


[Avatar]
Joined: 23/02/2007 17:22:13
Messages: 745
Location: São Paulo - SP - Brasil
Offline

O Mentawai propõe várias formas de se utilizar Ajax,
Porém existe uma biblioteca JavaScript que vem junto
com o Menta, que permite um fácil uso e entendimento de ajax no client-side.

Permitindo passar para action quantos parametros forem nescessários ou
um formulário inteiro e retornar para o ajax, um:

Map
List
String
Beans
HTML
ListData

O processo ajax se da por duas etapas,

Primaira é o Request, ou seja, a página requisita algo para o servidor
sem que haja reflesh de página.
Segunda é o callback/Response, que é uma função JavaScript que recebe
a resposta do servidor.

O Menta tem duas classes JavaScript que facilita muito o uso das duas
partes que compõem um ciclo ajax.

A primeria parte que é o Request, existe a classe JavaScript "mtw.request()"
que prepara o chamado para enviar ao servidor.
A segunda parte que é o Response, existe a classe JavaScript "mtw.response()"
que possui métodos para recuperação dos dados vindos do servidor.

A Classe mtw.request:

Métodos:

setUrl(url)
Seta a url que sera enviada ao servidor

onSuccess(callback)
Diz qual será o função que receberá o callback em caso de sucesso.

onError(callback)
Diz qual será o função que receberá o callback em caso de falha.

addParameter(key, value)
adiciona parametros para o request, exemplos:
setUrl("Test.mtw");
addParameter("nome", "Joao");
addParameter("idade", 20);
Produzirá a seguinte URL: Test.mtw?nome=Joao&idade=20

setMethod(method)
Seta o method que será utilizado, post/get , Default POST.

serializeForm(formId)
Envia os dados de um formulário inteiro para o servidor.
Obs: na versão 2.0 este método foi descontinuado.

send()
Envia a requisição.

useLoadingMessage(message)
Exibe um texto no canto superior enquanto o request é
executado.

waitComplete()
Espera o request ser executado completamente, ou seja, faz
um request sincrono, util para encadeamento de requests.

addRequestHeader(key, value)
Adiciona valores ao RequestHeader do request, exemplo
addRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate");

noCache()
Um atalho para
addRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0")
addRequestHeader("Pragma", "no-cache")

A Classe mtw.response:

Métodos:

getObject(index)
Retorna o objeto que esta no indice passado no parametro.
começando por 0 (zero)
Ex: se for passado um Map,
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("primeiro", "Um");
map.put("segundo", "Dois");
map.put("terceiro", "Tres");

var map = getObject(1) // retorna o segundo map
map.key // segundo
map.value // Dois

getValue(key)
Retorna o valor respectivo a chave passada, "Igual ao Map do Java".
Ex: se for passado um Map,
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("primeiro", "Um");
map.put("segundo", "Dois");
map.put("terceiro", "Tres");

var map = getValue("terceiro") // retorna o valor com chave "terceiro"
que equivale ao valor "Tres".

size()
Retorna o tamanho da lista de objetos.

getString()
Retorna uma simples String passada pela Action, ou conteúdo
de outras páginas.

innerHTML(id)
Substitui o conteúdo de um container.
resp.innerHTML("divId");

replaceOptions(id);
Remove e adiciona valores à combos Selects.
resp.replaceOptions("idSelect");

setValues();
Atualiza os elementos com os valores encontrados no
response, se utilizado um Map, a chave do map será
o id do elemento e o valor será o value. em caso
de um Bean, será usado como id a propriedade e como
valor o valor da propriedade.
EX: resp.setValues();

Abaixo exemplos em meio a um contexto que facilitará a visualização
do funcionamento desses metodos.


Existem tambem alguns métodos "Estáticos":

mtw.removeOptions("selectId");
Remove todas opções de um select

mtw.addOptions("selectId", response);
Adiciona ao select com id especificado, os valores
do response.


Executando um request:
Code:
 <script type="text/javascript">
 function getMap(transport) {
 	var res = new mtw.response(transport);
 
 }
 
 function doRequest() {
 	var req = new mtw.request();
 	req.setUrl("TestAction.getMap.mtw");
 	req.onSuccess(getMap);
 	req.send();
 }
 </script>
 

Ao chamar a função "doRequest()" ele envia para o servidor
a URL: TestAction.mtw e logo após o servidor enviar a resposta
ele chama a função especificado no onSuccess, enviando junto
o transport ajax.

Obs: "voce nem precisa saber oque é transport apenas passe-o
para o construtor do mtw.response.

De agora em diante voce já pode utilizar os metodos da classe
mtw.response para recuperar os dados.


Agora um exemplo na pratica

Bean Pessoa:
Code:
 public class Pessoa implements Serializable {
 	private String nome;
 	private String sobrenome;
 	private Integer idade;
 	private Date nascimento;
 
 	public Pessoa() {
 	}
 	
 	public Pessoa(String nome, String sobrenome, Integer idade, Date nascimento){
 		this.nome = nome;
 		this.sobrenome = sobrenome;
 		this.idade = idade;
 		this.nascimento = nascimento;
 	}
 
 	// getters and setter omitidos.
 

Os beans devem seguir o padrão JavaBeans, que tem que no mínimo
ter um Construtor padrão sem argumentos, implementar Serializable e
possuir metodos setter e getters.


Action TestAction:
Code:
 public class TestAction extends BaseAction {
 
 	Pessoa pessoaBean = null;
 	
 	@Override
 	public String execute() throws Exception {
 		throw new ActionException("Nothing here");
 	}
 
 	public String getListBean() {
 		List<Pessoa> list = new ArrayList<Pessoa>();
 		list.add(new Pessoa("Joao", "Silva Filho", 5, new Date()));
 		list.add(new Pessoa("Maria", "Bonita", 7, new Date()));
 		list.add(new Pessoa("Mario", "Santos", 8, new Date()));
 		output.setValue(AjaxConsequence.KEY, list);
 		return SUCCESS;
 	}
 
 	public String getMap() {
 		Map<String, String> map = new LinkedHashMap<String, String>();
 		map.put("primeiro", "Um");
 		map.put("segundo", "Dois");
 		map.put("terceiro", "Tres");
 		output.setValue(AjaxConsequence.KEY, map);
 		return SUCCESS;
 	}
 
 	public String getBean() {
 		String whatBean = input.getStringValue("whatBean");
 		Pessoa bean = new Pessoa();
 		if (whatBean.equals("robert")) {
 			bean.setNome("Robert");
 			bean.setSobrenome("Willian Gil");
 			bean.setIdade(21);
 			Calendar ca = Calendar.getInstance();
 			ca.set(1985, 11, 15);            // 15/12/1985
 			bean.setNascimento(ca.getTime());
 		} else {
 			bean.setNome("João");
 			bean.setSobrenome("Da Silva");
 		}
 		output.setValue(AjaxConsequence.KEY, bean);
 		return SUCCESS;
 	}
 	
 	public String sendBean(){
 		// get Bean from VOFilter and put it to response;
 		output.setValue(AjaxConsequence.KEY, pessoaBean);
 		return SUCCESS;
 	}
 
 	public String getSimpleString(){
 		String value = input.getStringValue("value");
 		output.setValue(AjaxConsequence.KEY, "Hello " + value);
 		return SUCCESS;
 	}
 
 }
 


No ApplicationManager:
Code:
 public class ApplicationManager extends org.mentawai.core.ApplicationManager {
 	
 	@Override
 	public void init() {
 		addGlobalFilter(new InjectionFilter());
 	}
 	
 	@Override
 	public void loadActions() {
 		action(TestAction.class)
 		.on(SUCCESS, new AjaxConsequence(new JSONGenericRenderer()))
 		.filter(new VOFilter(Pessoa.class, "pessoaBean"));
 	}
 	
 	@Override
 	public void loadLocales() {
 		LocaleManager.add(new Locale("pt", "BR")); 
 	}
 
 }
 

Observe que usei um VOFilter, para ilustrar que podemos passar
um bean instanciado e carregado com os valores vindos dos
forms com serializeForm, ou com addParameter da classe Javascript
mtw.request.

Obs: É muito importante carregar pelo menos um locale,
para que as conversões de data funcionem automaticamente sem problemas.


Com esta action podemos fazer varios exemplos como:
retornar uma String
retornar um MAP
retornar um Bean
retornar um List de beans.


Header JSP
Code:
 <head>
 <mtw:ajaxConfig />
 </head>
 

isso carregará as libs necessarias para tudo funcionar.

Trabalhando com MAP

Code:
 <html>
 
 <head>
 	<mtw:ajaxConfig />
 </head>
 
 <body>
 <script type="text/javascript">
 
 // Fazendo o Request
 
 function callAction() {
 	var call = new mtw.request();
 	call.onSuccess(handleMap);
 	call.setUrl("TestAction.getMap.mtw");
 	call.useLoadingMessage("Carregando...");
 	call.send();
 }
 
 
 // Recebendo a Resposta
 
 function handleMap(transport){
 	var response = new mtw.response(transport);
 	alert(response.getObject(2).key);
 	alert(response.getObject(2).value);
 	alert(response.getValue("primeiro"));
 }
 </script>
 </body>
 </html>
 

Ok, quando em algum lugar alguem chamar a função callAction, ele
fará a chamada para o servidor, que retornará o resultado
para a função "handleMap" juntamente com o transport, cujo é
passado no construtor da classe mtw.response na hora da
instanciação.

O primeiro alert mostrará: terceiro
O segundo alert mostrará: Tres
O terceiro alert mostrará: Um


Trabalhando com Bean

Voces notarão que o processo do Request é simples
e parecido dependendo do que se precisa passar
para a action como parametros.

Code:
 <html>
 
 <head>
 	<mtw:ajaxConfig />
 </head>
 
 <body>
 <script type="text/javascript">
 
 // Fazendo o Request
 
 function callAction() {
 	var call = new mtw.request();
 	call.onSuccess(handleBean);
 	call.addParameter("whatBean", "robert");
 	call.setUrl("TestAction.getBean.mtw");
 	call.useLoadingMessage("Loading...");
 	call.send();
 }
 
 
 // Recebendo a Resposta
 
 function handleBean(transport){
 	var response = new mtw.response(transport);
 	alert(response.getObject().nome);
 	alert(response.getObject().sobrenome);
 	alert(response.getObject().idade);
 	alert(response.getObject().nascimento);
 
         // Ou assim:
 //        var pessoa = response.getObject();
 //        alert( pessoa.nome );
 //        alert( pessoa.sobrenome );
 //        alert( pessoa.idade );
 //        alert( pessoa.nascimento );
 }
 </script>
 </body>
 </html>
 


Temos uma pequena mudança agora na função callAction
que é um addParameter, que enviará para a action
o atributo "whatBean" com valor "robert", esse valor
poderia vir de uma variavel, de um campo do html ou
qualquer outro lugar.

As seguintes Respostas São:

Primeiro alert: Robert
Segundo alert: Willian Gil
Terceiro alert: 21
Quarto alert: 15/12/1985

Repare tambem que não foi passado o indice para o metodo
getObject() , não é necessario pois temos apenas um bean.


Trabalhando com um List de Beans
Code:
 <html>
 
 <head>
 	<mtw:ajaxConfig />
 </head>
 
 <body>
 <script type="text/javascript">
 
 // Fazendo o Request
 
 function callAction() {
 	var call = new mtw.request();
 	call.onSuccess(handleListBean);
 	call.setUrl("TestAction.getListBean.mtw");
 	call.send();
 }
 
 
 // Recebendo a Resposta
 
 function handleListBean(transport){
 	var response = new mtw.response(transport);
 	var pessoa = null;
 	for( var index = 0; index < response.size(); index++) {
 		pessoa = response.getObject(index);
 		msg = "Nome: " + pessoa.nome;
 		msg += "  Sobrenome: " + pessoa.sobrenome;
                alert(msg);
 	}
 }
 </script>
 </body>
 </html>
 


Para essa nossa action que tem 3 objetos na lista, será exibido
3 alerts com "Nome: xxxxx Sobrenome: xxxxxx"

Como podem ver, funciona muito semelhante ao Map porem ao invés de usar
key e value para obter os valores, voce passa o nome dos atributos.

Trabalhando com String
Code:
 <html>
 
 <head>
 	<mtw:ajaxConfig />
 </head>
 
 <body>
 
       <input type="text" name="valor" id="valor" value="Write Here">
       <div id="stringHere"></div>
       
       <input type="button" value="Go" onclick="getString();">
 
 <script type="text/javascript">
 
 // Fazendo o Request e Response na mesma Função
 
 function getString(){
      var r = new mtw.request();
      r.setUrl("TestAction.getSimpleString.mtw");
      r.onSuccess(
          
             function(trans) {
                   var rq = new mtw.response(trans);
 	          $("stringHere").innerHTML = rq.getString();
               }
 
      );
      r.addParameter("value", $("valor").value);
      r.send();
 }
 </script>
 
 </body>
 </html>
 

Ao Clicar no botão será feito o request passando como parametro o
valor do campo text com id "valor"
será retornar pelo servidor uma simples string que será capturada
com o getString e será jogada dentro do div com id "stringHere"

Obs: Voce pode retornar codigos html!

Tambem como exemplo podemos observar que podemos aninhas
as funções, a função que manipula o response esta dentro do proprio
onSuccess();


Um exemplo de serialização de um Form
Code:
 <form action="" id="formBean">
 	Nome: <input type="text" name="nome" value="Fulano"><br>
 	Sobrenome: <input type="text" name="sobrenome" value="Chapado"><br>
 	Idade: <input type="text" name="idade" value="20"><br>
 	Nascimento: <input type="text" name="nascimento" value="15/12/1985"><br>
 </form>
 <div id="formDivId"></div>
 <script type="text/javascript">
 function fillForm(trans){
 	var r = new mtw.response(trans);
 	var data = r.getObject();
 	msg = "Nome: "+ data.nome;
 	msg += "<br>Sobrenome: " + data.sobrenome;
 	msg += "<br>Idade: "+ data.idade;
 	msg += "<br>Nascimento: " + data.nascimento;
 	document.getElementById("formDivId").innerHTML = msg;
 }
 
 function sendBean(){
 	var r = new mtw.request();
 	r.setUrl("TestAction.sendBean.mtw");
 	r.onSuccess(fillForm);
 	r.serializeForm("formBean");
 	r.send();
 }
 </script>
 <input type="button" value="SendBean" onclick="sendBean();">
 


Ao clicar no botão, será chamada a função sendBean, que enviará a

URL: TestAction.sendBean.mtw?nome=Fulado&sobrenome=Chapado&idade=20&nascimento=15%2F12%2F1985

como percebem a url vai codificada com o padrao de urlEncode,
e a função fillForm irá inserir o codigo html gerado pelo javaScript no
container com id "formDivId" via innerHTML


Combo Dinâmico.
Code:
  	<script type="text/javascript">
 			function requestSel(){
 				var r = new mtw.request();
 				r.setUrl("TestAction.getMap.mtw");
 				r.onSuccess(
 					function (trans){
 					var response = new mtw.response(trans);
 					response.replaceOptions("sel");
 					}
 				);
 				r.useLoadingMessage();
 				r.send();
 			}
 	</script>
 	<select id="sel" name="sel"></select>
 	<input type="button" value="Go" onclick="requestSel();">
 	
  


HTML Content
Code:
 		<script type="text/javascript">
 		function getHTML(){
 			var r = new mtw.request();
 			r.setUrl("jsp/other.jsp");
 			r.onSuccess(
 				function(data){
 					var resp = new mtw.response(data);
                                        resp.innerHTML("htmlHere");
 				}
 			);
 			r.send();
 		}
 		</script>
 		<div id="htmlHere"></div>
 		<br>
 		<input type="button" value="Get" onclick="getHTML();">
 

Este código pega o código HTML da pagina jsp/other.jsp e insere
no div "htmlHere".
Obs: Pose-se passar por uma action normalmente.


Update Field
Este exemplo usa um Bean ou um Map para atualizar os campos.

Bean Address
Code:
  public class Address implements Serializable {
  	private String country;
 	private int state;
 	private String city;
 
   //  Setter and Getter omitidos..
  }
  


Action AddressAction
Code:
  public class AddressAction extends BaseAction {
 	
 	public String getAddress(){
 		String mapOrBean = input.getStringValue("mapOrBean");
 		String cep = input.getStringValue("cep");
 		if(cep == null) cep = "null";
 		if(mapOrBean.equalsIgnoreCase("map")){
 			output.setValue(AjaxConsequence.KEY, getMap(cep));
 		} else {
 			output.setValue(AjaxConsequence.KEY, getBean(cep));
 		}
 		
 		return SUCCESS;
 	}
 	
 	private Map<String, String> getMap(String cep){
 		Map<String, String> map = new LinkedHashMap<String, String>();
 		if(cep.equalsIgnoreCase("11.111-111")){
 			map.put("country", "Brasil / MAP");
 			map.put("state", "1");
 			map.put("city", "Sorriso");
 			map.put("cor", "azul");
 		} else if(cep.equalsIgnoreCase("22.222-222")){
 			map.put("country", "Brasil / MAP");
 			map.put("state", "2");
 			map.put("city", "São Paulo");
 			map.put("cor", "vermelho");
 		} else {
 			map.put("country", "Não Encontrado! / MAP");
 			map.put("state", "0");
 			map.put("city", "Não Encontrado");
 		}
 		return map;
 	}
 	
 	private Address getBean(String cep){
 		Address addr = new Address();
 		
 		if(cep.equalsIgnoreCase("11.111-111")){
 			addr.setCountry("Brasil / BEAN");
 			addr.setState(1);
 			addr.setCity("Sorriso");
 			
 		} else if(cep.equalsIgnoreCase("22.222-222")){
 			addr.setCountry("Brasil / BEAN");
 			addr.setState(2);
 			addr.setCity("São Paulo");
 			
 		} else {
 			addr.setCountry("Não Encontrado / BEAN");
 			addr.setState(0);
 			addr.setCity("Não Encontrado");
 		}
 		return addr;
 	}
 
 }
  

Esta Action apenas pega dois parametros passados pela request ajax,
que é o "mapOrBean" para saber se queremos no response um
Bean ou Map, e conforme o valor do parametro é colocado no output
um Map, ou um Bean populado e o cep.

ApplicationManager:
Code:
  action(AddressAction.class)
      .on(SUCCESS, new AjaxConsequence(new JSONGenericRenderer()));
 
 //   Super Tiny Style
 //
 //  action(AddressAction.class).ajaxOK(new JSONGenericRenderer());
  


Jsp:
Code:
  	<fieldset>
 		<legend>Update Field</legend>
 		<script type="text/javascript">
 		function updateField(){
 			var r = new mtw.request();
 			r.setUrl("AddressAction.getAddress.mtw");
 			r.onSuccess(
 				function(data){
 					new mtw.response(data).setValues();
 				}
 			);
 			r.addParameter("mapOrBean", mtw.getValue("mapOrBean"));
 			r.addParameter("cep", mtw.getValue("cep"));
 			r.send();
 		}
 		</script>
 		<table>
 			<tr>
 				<td> <input type="radio" name="mapOrBean" value="map">Com Map </td>
 				<td> <input type="radio" name="mapOrBean" value="bean" checked="checked">Com Bean </td>
 			</tr>
 			<tr>
 				<Td>Cep:</Td>
 				<td><mtw:inputMask maskDefined="cep" name="cep" id="cep"/>     11.111-111 / 22.222-222</td>
 			</tr>
 			<tr>
 				<td>Pais</td>
 				<td><input type="text" id="country" name="country"></td>
 			</tr>
 			<tr>
 				<td>Estado:</td>
 				<td>
 					<select id="state" name="state">
 						<option value="0">Não Encontrado</option>
 						<option value="1">Mato Grosso</option>
 						<option value="2">São Paulo</option>
 					</select>
 				</td>
 			</tr>
 			<tr>
 				<td>Cidade:</td>
 				<td>
 					<input type="radio" name="city" value="Sorriso">Sorriso
 					<input type="radio" name="city" value="São Paulo"> São Paulo
 				</td>
 			</tr>
 			<tr>
 				<td><input type="checkbox" name="cor" value="azul">Azul</td>
 				<td><input type="checkbox" name="cor" value="vermelho">Vermelho</td>
 			</tr>
 			<tr>
 				<td><input type="button" value="Update" onclick="updateField();"></td>
 			</tr>
 		</table>
 	</fieldset>
  


Estes exemplos e outros são encontrados no war de exemplo
com os fontes, e podem ser baixado AQUI.

Jars requeridos.
ezmorph e json-lib-0.8 podem ser baixados Aqui

Bom é isso pessoal qualquer duvida, postem no fórum Mentawai.

Robert Gil
Coordenador de Desenvolvimento / Administrador de Redes.

Twitter
[Email] [MSN]
Lupos


[Avatar]

Joined: 19/04/2007 11:53:00
Messages: 75
Offline

Parabéns Robert.... ótimo trabalho... dá gosto de ver.



marcelow22



Joined: 24/11/2006 17:05:16
Messages: 12
Offline

bom dia amigos!

sou novo em programação java, e gosto muito do mentawai, pelas facilidades que ele tem.

Estou tentando usar o MentaAjax, e peguei os exemplos aqui deste topico, e funcionou perfeitamente, sem problemas!

Porém, quando eu substituo o arquivo mentawai.jar do exemplo, pelo mentawai.jar mais atual (o 1.14.1) os exemplos não funcionam mais!!

Estava querendo usar o mentawai.jar mais atual, por questão de novas funcionalidades, correção de bugs, etc. o Mentawai 1.14.1 não tem suporte para o mentaAjax??

O interessante é que não da nenhuma mensagem de erro, simplesmente não funciona! Qualquer exemplo do mentaAjax que você tentar rodar usando o mentawai.jar mais atual não funciona, e não da nenhuma mensagem de erro e nem nada.

Alguém ja conseguiu usar o mentaAjax no mentawai mais atual?? E se conseguiu, como fez??

muito obrigado!!

IceW0lf


[Avatar]

Joined: 16/03/2006 08:33:38
Messages: 1546
Location: Brasília
Offline

Que eu me lembre houve algumas mudanças..

Abre um post em DUVIDAS GERAIS sobre o assunto e post o codigo para que possam ajudar.

acho que vc deverá substituir mtw.getValue por isto mtw.util.getValue.

Leiber Wallace
Voixy ::: Soluções em Telecomunicações
Rubem Vieira



Joined: 13/12/2011 10:05:19
Messages: 2
Offline

Boa tarde a todos.

Bom estou começando a converter um sistema legado para o Mentawai, gostaria de saber se na Action tem como "forçar" um erro para que a função onError seja chamada.

Edit: Acabei de achar a resposta:
http://forum.mentaframework.org/posts/list/1873.page
 
Forum Index -> F.A.Q.
Go to:   
Powered by JForum 2.1.6 © JForum Team