Click - Programação Web orientada a Componentes e Eventos – Parte II
Neste artigo será apresentado o Click, um framework Orientado a Páginas e Componentes, e ainda possui um modelo de programação b...
Utilizando um “Listener” em um componente
Vamos adaptar o HelloWorld feito anteriormente. O código abaixo cria um simples formulário de pesquisa, e ainda define um “listener” que contém o método que irá responder aos eventos da tela, por exemplo ao clicar em um botão.
package click.exemplo.page;
import net.sf.click.Page;
import net.sf.click.control.Form;
import net.sf.click.control.Submit;
import net.sf.click.control.TextField;
public class PesquisaPage extends Page {
private TextField nome;
public Pesquisa() {
Form form = new Form("form");
//default é post
form.setMethod("get");
nome = new TextField("nome");
form.add(nome);
form.add(new Submit("buscar",this,"doSearch"));
addControl(form);
}
public boolean doSearch(){
addModel("mensagem","Você deseja buscar a pessoa: " + nome.getValue());
return true;
}
}
E a página pesquisa.htm:
$form
$!mensagem
Na página pesquisa.htm, basta adicionar o componente “$form”. Como um objeto Form foi adicionado como controle da página atual, será feito um toString() deste objeto, e consequentemente a form será renderizada automaticamente, incluindo todos os campos que foram adicionados nela. O resultado pode ser visualizado abaixo:
Note que a mensagem é visualizada apenas se existe uma variável mensagem no contexto, para isto é utilizado o caracter “!”, que é uma funcionalidade do Velocity, não do Click.
Criando o HTML manualmente
Antes de customizar o Form, verifique este exemplo do Click que mostra como customizar o layout utilizando apenas algumas propriedades da Form:
Vamos alterar o exemplo anterior, na página pesquisa.htm, e construir o Form manualmente, conforme visualizado abaixo:
$form.startTag()
<table class="form" id="form-form">
<tr><td>
<table class="fields" id="form-fields">
<tr class="fields">
<td class="fields" align="left"><label>Nome</label></td>
<td align="left">$form.fields.nome</td>
</tr>
</table>
</td></tr>
<tr><td align="left">
<table class="buttons" id="form-buttons">
<tr class="buttons"><td class="buttons">$form.fields.buscar</td></tr>
</table>
</td></tr>
</table>
</form>
$!mensagem
O método startTag da classe Form gera o seguinte código automaticamente:
<form method="get" name="form" id="form" action="/pesquisa.htm"><input type="hidden" name="form_name" id="form_form_name" value="form"/>
Para cada campo, por exemplo o campo “Nome”, é possível utilizar uma simples expressão em Velocity para mostrar o HTML correspondente na página.
Desta forma a expressão $form.fields.nome gera o seguinte HTML:
<input type="text" name="nome" id="form_nome" size="20"/>
O motivo é porque cada componente, possui o método toString() implementado para retornar o seu respectivo HTML.
No FAQ existem outras maneiras para customizar o HTML:
As mais utilizadas são macros (funções) do Velocity para encapsular um template em um único arquivo, ou fazer uma subclasse da Form, e sobrescrever o método toString(). Lembrando que isto pode ser feito para qualquer componente.
Validando o Formulário
Para validar os campos no Click, basta configurar seus respectivos componentes. No exemplo anterior, pode-se dizer que o campo “nome” é obrigatório da seguinte forma:
nome = new TextField("nome");
nome.setRequired(true);
Para que não seja feito o processamento no servidor deve-se testar se a Form é válida antes de realizar a busca:
public boolean doSearch(){
if (form.isValid()) {
addModel("mensagem", "Você deseja buscar a pessoa: " + nome.getValue());
return true;
}
return false;
}
- Note que é retornado “false”, para parar o processamento caso a Form seja inválida.
O resultado da tela será igual a imagem abaixo:
Se o layout da Form é manual, obviamente é necessário escrever o código para mostrar a mensagem de erro. Isto é feito através da expressão: “$form.fields.nome.error”.
Ainda é possível utilizar validação no lado do cliente com Java Script, basta configurar o Form, conforme abaixo:
form.setJavaScriptValidation(true);
Entendendo o Fluxo de Execução
Para utilizar o Click, é necessário entender a ordem em que os métodos e eventos são executados. Na imagem em vermelho, estão destacados 5 pontos importantes no diagrama de sequência que representa o algoritmo do ClickServlet:
Ao iniciar uma requisição ao servidor, o ClickServlet executa os seguintes passos:
- Cria a página (Page);
- O construtor da classe Page é chamado (reflexão - class.newInstance);
- Após criar a Page, é invocado o método page.setContext(context), para armazenar o objeto “net.sf.click.Context”, que possui informações sobre o objeto Request da API de Servlets, assim como métodos de internacionalização, como o getMessage();
- O método onInit() é chamado. A diferença entre o construtor da Page e o onInit() é que o objeto Context já está setado no onInit(). É no construtor e no método onInit() que os objetos do tipo Control precisam ser adicionados na Page (utilizando o método addControl() ou atributos públicos);
- Cada “listener” para os componentes (Submit, ActionLink, ActionButton, Table, Form, etc) são executados. Os listeners são os métodos definidos pelo programador para conter a lógica de negócios. O ideal é chamar uma outra classe de negócios mais especializada para não poluir o código da Page, tornando o código mais limpo, e deixando a manutenção da aplicação mais simples;
- Dependendo do tipo da request, o método onGet() ou onPost() é chamado
- O método onRender() é executado. O onRender() é extramente útil para executar um código independente de qual o tipo da request (get ou post).
Para entender exatamente a ordem em que os métodos são executados, crie a página “eventos.htm” e a classe “EventosPage.java”.
eventos.htm
$link
<br>
$form
EventosPage.htm
package click.exemplo.page;
public class EventosPage extends Page {
public ActionLink link = new ActionLink("link",this,"onClick");
public Form form = new Form();
public EventosPage() {
print("1 - constructor(). Context está null: " + getContext());
}
public void onInit() {
print("2 - onInit(). Context: " + getContext());
form.add(new Submit("Post"));
form.add(new Submit("Post + Listener",this,"onSubmit"));
}
public boolean onClick() {
print("3 - onClick() listener method");
return true;
}
public boolean onSubmit() {
print("3 - onSubmit() listener method");
return true;
}
public void onGet() {
print("4 - onGet()");
}
public void onPost() {
print("4 - onPost()");
}
public void onRender() {
print("5 - onRender()");
}
}
A seguinte tela vai aparecer no exemplo, e a ordem da execução dos métodos da classe vai depender de qual botão ou link você clicar.
A classe net.sf.click.Context
A classe Context possui muitos métodos utilitários, como por exemplo acessar a HttpServletRequest.
HttpServletRequest request = getContext().getRequest();
Object requestAttribute = getContext().getRequestAttribute("x");
String requestParameter = getContext().getRequestParameter("x");
HttpSession session = getContext().getSession();
Object sessionAttribute = getContext().getSessionAttribute("x");
Locale locale = getContext().getLocale();
ServletConfig servletConfig = getContext().getServletConfig();
ServletContext servletContext = getContext().getServletContext();
Ricardo Rodrigues Lecheta
Ricardo Rodrigues Lecheta (ricardolecheta@terra.com.br), é autor do livro “Google Android” - Aprenda a criar aplicações para dispositivos móveis utilizando o Android SDK e possui as certificações SCJP, SCWCD, SCBCD, SCMAD, SCEA.




