Sencha GXT 3 (Ext GWT): Exemplo Grid Simples

No post de hoje vamos aprender passo a passo como implementar um Grid simples usando Sencha GXT 3, também conhecido como Ext GWT 3.

Requisitos:

  • Eclipse
  • Google plugin para Eclipse
  • Sencha GXT 3

Se você não souber como configurar o ambiente, pode ler esse tutorial que mostra o passo a passo de como fazer isso.

Passo a passo:

  • Criar o Projeto
  • Criar o código GXT 3
  • Criar a classe Entry Point (public static void main do GWT)
  • Executar o projeto
Segue screenshot do projeto do exemplo que vamos implementar nesse post:

1- Criando o Projeto

A primeira coisa que precisamos é criar o projeto e adicionar o jar do GXT 3. Segue o passo a passo:

1.1 - Para criar um novo projeto, clique na “seta para baixo” ao lado do ícone do Google e selecione “New Web Application Project”:

1.2 - Dê um nome para o projeto (neste tutorial dei o nome de sencha-gxt3-simple-grid), informe o nome do pacote base que irá usar (neste caso escolhi com.loiane.gxt3). Depois deixe apenas a opção “Use Google Web Toolkit” selecionada. Assim vamos criar um projeto “zerado”:

1.3 - Depois adicione a biblioteca do GXT 3 no projeto. Este post mostra como fazer isso.

2 - Criando o Grid com Sencha GXT 3

2.1 - Agora que o projeto já está todo configurado, vamos começar com a diversão e implementar a nossa aplicação com GXT 3. Para isso, selecione o projeto, clique com o botão direto e escolha “New” -> “Other”. Ache o folder do “Google Web Toolkit” e escolha “Module”:

2.2 - Escolha o pacote (que escolhemos quando criamos o projeto, lembra?) e dê um nome para o módulo. Chamei o módulo de SimpleGrid. Outro detalhe é que se reparamos na parte de Inherited modules, apenas o com.google.gwt.user.User vem por padrão. Como vamos desenvolver uma aplicação com GXT, também precisamos adicionar o módulo da Sencha, que o o com.sencha.gxt.ui.GXT. Para isso, basta clicar no botão "Add" e procurar por essa classe. Depois de tudo pronto, basta clicar no botão "Finish":

Repare que o plugin do Google irá gerar a estrutura de pacotes (nesse caso com.loiane.gxt3.client) e um arquivo xml com a configuração do módulo que acabamos de criar.

2.3 - Agora podemos começar a codificar! O Primeiro passo é criar um POJO que represente o dado que queremos mostrar no Grid. Nesse exemplo vamos criar uma classe simples que representa um contato. Vou colocar essa classe dentro do pacote com.loiane.gxt3.client.model e essa classe também precisa implementar a interface Serializable:

2.4 - Depois que a classe está criada, vamos adicionar os atributos, métodos getters e setter e dois construtores: um vazio e um que recebe todos os atributos:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.gxt3.client.model;

import java.io.Serializable;

public class Contact implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;
private String name;
private String phone;
private String email;

public Contact(){
super();
}

public Contact(Integer id, String name, String phone, String email) {
super();
this.id = id;
this.name = name;
this.phone = phone;
this.email = email;
}

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
[/code]

2.5 - Para o grid, vamos precisar configurar as colunas que vão aparecer no grid. As colunas irão mostrar os dados que representam os atributos que acabamos de criar na classe Contact. E para configurarmos as colunas do grid, o GXT 3 precisa de uma classe Properties, que nós vamos criar agora:

2.6 - A classe ContactProperties vai ficar assim:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.gxt3.client.model;

import com.google.gwt.editor.client.Editor.Path;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.PropertyAccess;

public interface ContactProperties extends PropertyAccess<Contact> {

@Path("id")
ModelKeyProvider<Contact> key();

ValueProvider<Contact, String> name();

ValueProvider<Contact, String> phone();

ValueProvider<Contact, String> email();
}
[/code]

E a pergunta que não quer calar: O que é essa tal interface PropertyAccess? Essa interface serve para que o grid consiga acessar os atributos da classe POJO que criamos.  Precisamos criar um método para acessar cada atributo que criamos na nossa classe Contact. Esse métodos podem retornar um ModelKeyProvider ou ValueProvider (no nosso caso). O ModelKeyProvider significa que tem um retorno único, como por exemplo, o id do registro que vai ser retornado do banco de dados; neste caso ainda usamos a anotação Path para dizer que esse método serve para acessar o atributo id da classe Contact. Os outros métodos são do tipo ValueProvider, o que significa que vamos acessar diretamente o valor dos outros atributos, que queremos mostrar no grid.

2.7 - Agora já temos tudo pronto para criar o código do Grid em GXT 3. Vamos criar uma nova classe que extende da classe Grid do GXT 3:

2.8 - Bem, para implementarmos um Grid simples simples, precisamos de apenas 2 coisas: da configuração de colunas (afinal, precisamos dizer quais são as colunas que irão aparecer no grid né?), e uma store, que é responsável por popular o grid com dados.

Primeiro vamos então criar a configuração das colunas:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
private static final ContactProperties props = GWT.create(ContactProperties.class);

private static ColumnConfig<Contact, String> nameCol = new ColumnConfig<Contact, String>(props.name(), 150, "Name");
private static ColumnConfig<Contact, String> phoneCol = new ColumnConfig<Contact, String>(props.phone(), 75, "Phone");
private static ColumnConfig<Contact, String> emailCol = new ColumnConfig<Contact, String>(props.email(), 150, "Email");

private static ColumnModel<Contact> createColumnModel(){

List<ColumnConfig<Contact, ?>> columnConfigList = new ArrayList<ColumnConfig<Contact, ?>>();
columnConfigList.add(nameCol);
columnConfigList.add(phoneCol);
columnConfigList.add(emailCol);

return new ColumnModel<Contact>(columnConfigList);
}
[/code]

Na linha 1 temos a instância da classe ContactProperties que criamos no passo anterior. Logo abaixo temos mais 3 atributos que representam a configuração de 3 colunas. E logo depois temos um método que retorna um objeto do tipo ColumnModel que vamos setar no grid daqui a pouco. Para quem já tem experiência com ExtJS, pode notar que é praticamente a mesma coisa, só que agora estamos codificando em java ao invés de codificar com javascript. E para quem nunca trabalhou com ExtJS, sugiro que estude esses conceitos do ExtJS.

Agora precisamos criar a Store:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
private static ListStore<Contact> generateData(){

ListStore<Contact> store = new ListStore<Contact>(props.key());
store.addAll(ContactTestData.generateData());

return store;
}
[/code]

Como nesse primeiro exemplo criei apenas alguns dados manualmente para popular a store, criei essa classe ContactTestData. Em um próximo post veremos como buscar esses dados diretamente de um banco de dados:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.gxt3.client.util;

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

import com.loiane.gxt3.client.model.Contact;

public class ContactTestData {

public static List<Contact> generateData(){

List<Contact> list = new ArrayList<Contact>();

list.add(new Contact(1, "Loiane", "1234-5678", "loiane@email.com"));
list.add(new Contact(2, "Peter", "2345-6789", "peter@email.com"));
list.add(new Contact(3, "Andrew", "9876-1234", "andrew@email.com"));
list.add(new Contact(4, "Caroline", "5647-8473", "caroline@email.com"));
list.add(new Contact(5, "Jared", "4034-4585", "jared@email.com"));
list.add(new Contact(6, "Linda", "3455-0234", "linda@email.com"));
list.add(new Contact(7, "Elena", "3454-4543", "elena@email.com"));
list.add(new Contact(8, "Stefan", "5677-5677", "stefan@email.com"));
list.add(new Contact(9, "Ana", "2434-2343", "ana@email.com"));

return list;
}
}
[/code]

Por último, só falta a gente adicionar a store e o columnModel ao grid, e vamos fazer isso através do construtor. Adicionei também umas configuração para deixar o grid mais bonito, mas para criar o grid mesmo só precisamos da instância!

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
public SimpleGrid() {

super(generateData(), createColumnModel());

this.getView().setStripeRows(true);
this.getView().setColumnLines(true);
this.getView().setAutoExpandColumn(nameCol);
this.setBorders(false);
this.setColumnReordering(true);
}
[/code]

A classe SimpleGrid fica assim então:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.gxt3.client.grid;

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

import com.google.gwt.core.client.GWT;
import com.loiane.gxt3.client.model.Contact;
import com.loiane.gxt3.client.model.ContactProperties;
import com.loiane.gxt3.client.util.ContactTestData;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;

public class SimpleGrid extends Grid<Contact> {

private static final ContactProperties props = GWT.create(ContactProperties.class);

private static ColumnConfig<Contact, String> nameCol = new ColumnConfig<Contact, String>(props.name(), 150, "Name");
private static ColumnConfig<Contact, String> phoneCol = new ColumnConfig<Contact, String>(props.phone(), 75, "Phone");
private static ColumnConfig<Contact, String> emailCol = new ColumnConfig<Contact, String>(props.email(), 150, "Email");

public SimpleGrid() {

super(generateData(), createColumnModel());

this.getView().setStripeRows(true);
this.getView().setColumnLines(true);
this.getView().setAutoExpandColumn(nameCol);
this.setBorders(false);
this.setColumnReordering(true);
}

private static ColumnModel<Contact> createColumnModel(){

List<ColumnConfig<Contact, ?>> columnConfigList = new ArrayList<ColumnConfig<Contact, ?>>();
columnConfigList.add(nameCol);
columnConfigList.add(phoneCol);
columnConfigList.add(emailCol);

return new ColumnModel<Contact>(columnConfigList);
}

private static ListStore<Contact> generateData(){

ListStore<Contact> store = new ListStore<Contact>(props.key());
store.addAll(ContactTestData.generateData());

return store;
}
}
[/code]

3 - Criando a Classe EntryPoint

3.1 - Tudo pronto! Só precisamos criar agora uma maneira de chamar esse código todo que acabamos de criar! Para isso, vamos criar uma classe EntryPoint, que possui um método chamado onModuleLoad, que é uma espécie de método main do GWT:

3.2 - Vamos criar a classe:

3.3 - Vamos ao código então:

[code lang="java" firstline="1" toolbar="true" collapse="false" wraplines="false"]
package com.loiane.gxt3.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.loiane.gxt3.client.grid.SimpleGrid;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.Resizable;
import com.sencha.gxt.widget.core.client.Resizable.Dir;

public class SimpleGridExample implements EntryPoint {

@Override
public void onModuleLoad() {

ContentPanel root = new ContentPanel();

root.setHeadingText("Simple Grid");
root.setPixelSize(550, 250);
root.addStyleName("margin-10");

Resizable r = new Resizable(root, Dir.E, Dir.SE, Dir.S);
r.setMinHeight(200);
r.setMinWidth(300);

root.setWidget(new SimpleGrid());

RootPanel.get().add(root);
}

}
[/code]

No código acima apenas criamos um painel que pode ser redimencionado e adicionamos o grid como o único item. O painel será renderizado dentro da tag body do html.

3.4 - Falando em HTML, só falta agora criar a página html dentro da pasta war:

[code lang="html" firstline="1" toolbar="true" collapse="false" wraplines="false"]
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Simple Grid Example - loiane.com</title>

<link rel="stylesheet" type="text/css" href="simplegrid/reset.css" />

<style type="text/css">
body {
padding: 30px;
}
</style>

<script type="text/javascript" language="javascript" src="simplegrid/simplegrid.nocache.js"></script>
</head>

<body>
</body>
</html>
[/code]

4 - Executando o Projeto

4.1 - Para executar o projeto, vamos clicar novamente com o botão direito no projeto, e escolher a opção “Run As” -> “Web Application” (repare no ícone do plugin do Google)!

5 - Download Código Fonte

Para fazer download do código fonte completo (ou fazer um fork) do repositório do github: https://github.com/loiane/sencha-gxt3-simple-grid

Até a próxima! :)