[Logo] Mentawai Forum - Mentawai Web Framework
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
Lista com conteúdo dinâmico  XML
Forum Index -> Comentários Gerais
Author Message
andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

A pedido do Sérgio estou criando dois novos tópicos para encontrarmos alguma maneira de solucionarmos 2 problemas que encontrei. O segundo vou colocar no tópico: Formulário com passos.

O primeiro já foi mencionado pelo boaglio, quando mencionou a necessidade de termos um combo que tem seus valores alterados devido a seleção feita em um outro com combo.

Acho que precisamos no Mentawai suporte para que as listas possam ser filtradas, para que possamos utilizando um tag como <mtw:select> passarmos um condição para os valores que serão apresentados.

Foi comentada a possibilidade de usarmos AJAX, porém caso não queiramos depender do browser, e utilizarmos uma solução “em servidor” o Mentawai nos possibilite isso.

Estou precisando de uma solução para esse problema.


André Delorme
boaglio


[Avatar]

Joined: 28/09/2005 11:05:16
Messages: 299
Location: Sao Paulo - Brazil
Offline


Acredito que uma vez padronizado, poderemos utilizar soluções que utilizem javascript.

Para evitar a geração de arquivos HTML gigantes como o Struts faz, poderíamos usar arquivos nessa estrutura:

/ - raiz
/js/mentawai.js
/css/mentawai.css (se necessário)

E até aproveitar essa estrutura mesmo para implementar valições no cliente.

http://www.boaglio.com
[WWW]
andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

Pessoal, criei 2 tags personalizadas para solucionar esse problema. Aqui não me preocupei com o internacionalização.

Usando como base um código semelhante ao postado em http://mentaforum.lohis.com.br/posts/list/50.page

Criei um tld com as 2 definições:
Code:
     <tag>
         <name>selectParent</name>
         <tag-class>SelectParent</tag-class>
         <body-content>empty</body-content>
         <display-name></display-name>
       <attribute>
         <name>name</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <type>java.lang.String</type>
       </attribute>
       <attribute>
         <name>list</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <type>java.lang.String</type>
       </attribute>
       <attribute>
         <name>noSelect</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>boolean</type>
       </attribute>	  
       <attribute>
         <name>size</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>int</type>
       </attribute>	  	  
       <attribute>
         <name>emptyField</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>boolean</type>
       </attribute>	  	  	  
       <attribute>
         <name>id</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>String</type>
       </attribute>	  	  	  
       <attribute>
         <name>klass</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>String</type>
       </attribute>	  	  	  	  
       <attribute>
         <name>multiple</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>boolean</type>
       </attribute>	  	  	  	        
       <attribute>
         <name>newFormAction</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <type>java.lang.String</type>
       </attribute>
     </tag>
     <tag>
         <name>selectChild</name>
         <tag-class>SelectChild</tag-class>
         <body-content>empty</body-content>
         <display-name></display-name>
       <attribute>
         <name>name</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <type>java.lang.String</type>
       </attribute>
       <attribute>
         <name>list</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <type>java.lang.String</type>
       </attribute>
       <attribute>
         <name>noSelect</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>boolean</type>
       </attribute>	  
       <attribute>
         <name>size</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>int</type>
       </attribute>	  	  
       <attribute>
         <name>id</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>String</type>
       </attribute>	  	  	  
       <attribute>
         <name>klass</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>String</type>
       </attribute>	  	  	  	  
       <attribute>
         <name>multiple</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
         <type>boolean</type>
       </attribute>	  	  	  	        
       <attribute>
         <name>parentField</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <type>java.lang.String</type>
       </attribute>
     </tag>
 


As classes que as implementão:
Code:
 public class SelectParent extends HTMLTag {
     
     private String name;
     private String listname;
     private boolean noSelect = false;
     private int size = -1;
     private boolean emptyField = false;
     private String klass = null;
     private String id = null;
     private boolean multiple = false;
     
     private String newFormAction = null;
     
     public void setName(String name) { this.name = name; }
     public void setList(String listname) { this.listname = listname; }
     public void setNoSelect(boolean noSelect) { this.noSelect = noSelect; }
     public void setSize(int size) { this.size = size; }
     public void setEmptyField(boolean emptyField) { this.emptyField = emptyField; }
     public void setKlass(String klass) { this.klass = klass; }
     public void setId(String id) { this.id = id; }
     public void setMultiple(boolean multiple) { this.multiple = multiple; }
     
     public void setNewFormAction(String newFormAction) { this.newFormAction = newFormAction; }
     
     protected StringBuffer buildTag() {
         StringBuffer sb = new StringBuffer(150);
         sb.append("<select name=\"");
         sb.append(name);
         sb.append("\"");
         if (size > 1) sb.append(" size=\"").append(size).append("\"");
         if (klass != null) sb.append(" class=\"").append(klass).append("\"");
         if (id != null) sb.append(" id=\"").append(id).append("\"");
         if (multiple) sb.append(" multiple=\"true\"");
         
         sb.append(" onChange=\"").append("this.form.action='").append(newFormAction).append("';this.form.submit();").append("\"");
         
         return sb;
     }
     
     public String getStringToPrint() throws JspException {
         
         int [] values = findValues(name);
         
         ListData list = ListManager.getList(listname);
         
         StringBuffer sb = new StringBuffer(list.size() * 50);
         Iterator iter = list.getValues(loc).iterator();
         
         if (!noSelect) {
             sb.append(buildTag().toString());
             sb.append(">\n");
         }
         
         if (emptyField) {
             sb.append("<option value=\"0\"> - </option>\n");
         }
         
         while(iter.hasNext()) {
             ListDataItem item = (ListDataItem) iter.next();
             int id = item.getId();
             String n = item.getValue();
             
             sb.append("<option value=\"");
             sb.append(id);
             sb.append("\"");
             if (contains(values, id)) {
                 //sb.append(" SELECTED>");
                 sb.append(" selected=\"true\">");
             } else {
                 sb.append(">");
             }
             
             sb.append(n).append("</option>\n");
         }
         
         if (!noSelect) {
             sb.append("</select>\n");
         }
         
         return sb.toString();
     }
     
     
 }
 


Code:
 public class SelectChild extends HTMLTag {
     
     private String name;
     private String listname;
     private boolean noSelect = false;
     private int size = -1;
     //private boolean emptyField = false;
     private String klass = null;
     private String id = null;
     private boolean multiple = false;
     
     private String parentField = null;
     
     public void setName(String name) { this.name = name; }
     public void setList(String listname) { this.listname = listname; }
     public void setNoSelect(boolean noSelect) { this.noSelect = noSelect; }
     public void setSize(int size) { this.size = size; }
     //public void setEmptyField(boolean emptyField) { this.emptyField = emptyField; }
     public void setKlass(String klass) { this.klass = klass; }
     public void setId(String id) { this.id = id; }
     public void setMultiple(boolean multiple) { this.multiple = multiple; }
     
     public void setParentField(String parentField) { this.parentField = parentField; }
     
     protected StringBuffer buildTag() {
         StringBuffer sb = new StringBuffer(150);
         sb.append("<select name=\"");
         sb.append(name);
         sb.append("\"");
         if (size > 1) sb.append(" size=\"").append(size).append("\"");
         if (klass != null) sb.append(" class=\"").append(klass).append("\"");
         if (id != null) sb.append(" id=\"").append(id).append("\"");
         if (multiple) sb.append(" multiple=\"true\"");
         
         return sb;
     }
     
     public String getStringToPrint() throws JspException {
         
         int [] values = findValues(name);
         
         ListData list = ListManager.getList(listname);
         
         StringBuffer sb = new StringBuffer(list.size() * 50);
         Iterator iter = list.getValues(loc).iterator();
         
         if (!noSelect) {
             sb.append(buildTag().toString());
             sb.append(">\n");
         }
         
         //if (emptyField) {
         sb.append("<option value=\"0\"> - </option>\n");
         //}
         
         while(iter.hasNext()) {
             ListDataItemParent item = (ListDataItemParent) iter.next();
             int id = item.getId();
             String n = item.getValue();
             int idParent = item.getIdParent();
             
             String parentValue = findValue(parentField);
             System.out.println(id + "-" + parentValue + "-" + idParent);
             if (parentValue != null && parentValue.equals(new Integer(idParent).toString())) {
                 
                 sb.append("<option value=\"");
                 sb.append(id);
                 sb.append("\"");
                 if (contains(values, id)) {
                     //sb.append(" SELECTED>");
                     sb.append(" selected=\"true\">");
                 } else {
                     sb.append(">");
                 }
                 
                 sb.append(n).append("</option>\n");
             }
         }
         
         if (!noSelect) {
             sb.append("</select>\n");
         }
         
         return sb.toString();
     }
     
     
 }
 


Precisei estender o ListDataItem:
Code:
 public class ListDataItemParent extends ListDataItem {
     
     private int idParent;
     
     public ListDataItemParent(int id, String value, int idParent) {
         super(id, value);
         this.idParent = idParent;
     }
 
     public int getIdParent() {
         return idParent;
     }
 
     public void setIdParent(int idParent) {
         this.idParent = idParent;
     }
     
 }
 


E também estendi o DBListData, onde precisei adicionar o construtor DBListData():
Code:
 public class DBListDataParent extends DBListData {
     
     String idParentColumn;
     
     public DBListDataParent(ConnectionHandler connHandler, String table, String idColumn, String descriptionColumn, String idParentColumn) {
         this.table = table;
         this.idColumn = idColumn;
         this.descriptionColumn = descriptionColumn;
         this.idParentColumn = idParentColumn;
         
         try {
             Connection conn = connHandler.getConnection();
             String sql = "SELECT DISTINCT COUNT(" + idColumn + ") AS size FROM " + table;
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery();
             if (rs.next()) {
                 size = rs.getInt("size");
             }
             rs.close();
             pstmt.close();
             
             sql = "SELECT " + idColumn + ", " + descriptionColumn + ", " + idParentColumn + " FROM " + table;
             pstmt = conn.prepareStatement(sql);
             rs = pstmt.executeQuery();
             while (rs.next()) {
                 ListDataItemParent item = new ListDataItemParent(rs.getInt(idColumn), rs.getString(descriptionColumn), rs.getInt(idParentColumn));
                 list.add(item);
             }
             rs.close();
             pstmt.close();
             connHandler.release(conn);
         } catch (SQLException sqle) {
         }
     }
     
     
 }
 


No ApplicationManager tenho:
Code:
     public void loadLists() throws IOException {
         ListManager.init();
         DBListData uf = new DBListData(connHandler, "uf", "id_uf", "desc_uf");
         ListManager.addList(uf);
         DBListDataParent municipio = new DBListDataParent(connHandler, "municipio", "id_municipio", "desc_municipio", "id_uf");
         ListManager.addList(municipio);
     }
 


E sua utilização em paginas JSP fica, onde pageReload é apenas uma SuccessAction:
Code:
 Estado:
 <user:selectParent name="id_uf" list="uf" klass="formselect" emptyField="true" newFormAction="pageReload.mtw" />
 Município:
 <user:selectChild name="id_municipio" list="municipio" klass="formselect" parentField="id_uf"/>
 


O que vocês acham?


André Delorme
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline

Muito bom André... Vou analisar isso para incorporar no Mentawai.

Apenas um detalhe. Isso só funciona para 2 níveis né? Funcionaria com País, Estado e Cidade ???


Sergio Oliveira

boaglio


[Avatar]

Joined: 28/09/2005 11:05:16
Messages: 299
Location: Sao Paulo - Brazil
Offline

Não tem javascript ?

http://www.boaglio.com
[WWW]
andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

Sergio,

Pensei nisso, e vi que não é muito difícil, posso incorporar as duas funcionalidades num único TAG, se um atributo fosse incluído ela seria Parent, se o outro atributo fosse utilizado ela seria Child, e caso os 2 fossem utilizados eles seria intermediário.

Com isso eu poderia ter N níveis.

O que acha?


André Delorme
andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

boaglio,

O único JavaScript existente é a adição de:

Code:
 onChange="this.form.action='<newFormAction>';this.form.submit();"
 


no SELECT, alterando a URL para uma outra Action (parâmetro da Tag Customizada) e submentendo o formulário. Recarregando assim a página com a combo filha atualizada.

Entendeu?


André Delorme
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline

Não entendi muito bem não, mas de repente vai funcionar sim...

Tenta aí... Seria legal fazer um HelloMultilevelCombos.war... Vou ver se consigo fazer aqui com o seu código...

Sergio Oliveira

andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

Sergio,

Posso tentar fazer esse exemplo depois, mas agora estou tentando solucionar o outro problema que tenho, estou tentando criar uma tag <loopFields> para repetir os campos que estiverem presentes dentro da tag mas com um indexador para podermos ter vários endereços, por exemplo.


Agora o codígo é simples de enteder.

A <selectParent> apenas adiciona o código JavaScript que recarrega a página passando por uma SuccessAction (pelo menos no meu caso). Utilizando o atributo newFormAction

Já a <selectChid> contém um atributo parentField onde devemos colocar o nome do campo que determina o ID do pai, posso colocar um condicional na Classe para fazer a consulta condicional as campos da lista somente se este for preenchido.

O segredo é a alteração do ListDataItem para além do Id e Value, também conter o IdParent que é comparado com a seleção do Combo pai antes da apresentação, somente os que são relacionados ao pai são paresentados.

Essa tag funciona bem com Listas vindas de Banco, no caso das listas em arquivos do diretórios /lists acho que seria mais chato, pois teriamos que ter coisas como:

estados_pt_BR.i18n
=============
1 = RJ
2 = SP
...

cidades_pt_BR.i18n
=============
1 = 1|Rio de Janeiro
2 = 1|Niterói
3 = 2|São Paulo
4 = 2|Campinas
...

Certo?


André Delorme
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline

andredelorme wrote:
Posso tentar fazer esse exemplo depois, mas agora estou tentando solucionar o outro problema que tenho, estou tentando criar uma tag <loopFields> para repetir os campos que estiverem presentes dentro da tag mas com um indexador para podermos ter vários endereços, por exemplo.

 


Não entendi. O teu problema é o index que não pode ser sequencial ???


Sergio Oliveira

andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

Sergio,

Minha idéia é criar uma TAG para delimitar os campo que seriam repetidos e nomear o agrupamento, como:
Code:
 <user:loopFields name=”endereco”>
 <user:input type=”button” value=”remover” />
 Logradouro:
 <user:input type="text" name=”logradouro” />
 <br>
 Número:
 <user:input type="text" name=”numero” />
 <br>
 Complemento:
 <user:input type="text" name=”complemento” />
 </user:loopFiels>
 


Com isso esses campos seriam replicados N vezes, e o nome dos campos no HTML final gerado seriam, por exemplo: logradouro_1, logradouro_2, ..., logradouro_N (por isso, os tags INPUT também precisariam ser alterados).

O botão de remover alteraria por JavaScript (assim como fiz com as combos dinâmicas) o Action do Form. Esta trataria de remover o grupo de campos selecionado.

Além desses campos acho que seriam precisos mais dos TAGs, um para adicionar um novo grupo, algo como:
Code:
 <user:addOneMore name=“endereco” />
 

Que enviaria o formulário para o nova Action que incrementaria o controle de quantos endereços existem atualmente, e acrescentaria mais um grupo de campos. E para finalizar precisaríamos de mais um tag, como:
Code:
 <user:loopControl name=”endereco” />
 

Que apenas geraria um tag HTML HIDDEN, com um campo com o contador de quantos endereços existem atualmente, que seria usado pelas outras ações para inclusão ou remoção de um grupo de campos.

O que você acha? Fui muito confuso na explicação?

Depois ainda teria que verificar como os filtros de validação funcionariam.


André Delorme
andredelorme



Joined: 20/07/2005 11:41:46
Messages: 51
Offline

Sergio,

Consegui algo, criei uma TAG chamada <user:loopFields></user:loopFields>

Code:
 public class LoopFields extends LoopTag {
     
     private int count;
     private String counterField;
     
     public void setCounterField(String counterField) {
         this.counterField = counterField;
     }
     
     public boolean loopCondition() throws javax.servlet.jsp.JspException {
         return count-- > 0;
     }
     
     public void init() throws javax.servlet.jsp.JspException {
         Action action = (Action) request.getAttribute(Forward.ACTION_REQUEST);
         Input input = action.getInput();
         count = input.getIntValue(counterField);
         
     }
     
 }
 


TLD:
Code:
 <tag>
   <name>loopFields</name>
   <tag-class>andredelorme.caprev.tags.LoopFields</tag-class>
   <body-content>JSP</body-content>
   <display-name></display-name>
   <attribute>
     <name>counterField</name>
     <required>true</required>
     <rtexprvalue>true</rtexprvalue>
     <type>java.lang.String</type>
   </attribute>
 </tag>
 


Para utilizá-la, no meu JSP coloquei:
Code:
 <input type="button" value="Adicionar" onclick="this.form.action='enderecoAdd.mtw';this.form.submit();">
 
 <mtw:input type="hidden" name="enderecoCount" />
 <% int i = 0; %>
 <user:loopFields counterField="enderecoCount">
 Endereço: <%= ++i  %>
 <input type="button" value="Remover" onclick="this.form.action='enderecoDel.mtw?i=<%= i %>';this.form.submit();">
 
 Logradouro: <mtw:input type="text" name="<%= "logradouro_" + i %>" maxlength="100" size="50" />
 <br>
 Bairro: <mtw:input type="text" name="<%= "bairro_" + i %>" maxlength="50" size="30" />
 …
 
 </user:loopFields>
 


Action para adicionar um endereço:
Code:
 public class EnderecoAdd extends BaseAction implements org.mentawai.filter.AuthenticationFree {
     
     public String execute() throws org.mentawai.core.ActionException {
         int counter = 0;
         counter = input.getIntValue("enderecoCount");
         counter++;
         input.setValue("enderecoCount", new Integer(counter));
         return SUCCESS;
     }
     
 }
 


Action para remover um endereço:
Code:
 public class EnderecoDel extends BaseAction implements org.mentawai.filter.AuthenticationFree {
     
     public String execute() throws org.mentawai.core.ActionException {
         int counter = 0;
         int toRemove = 0;
         counter = input.getIntValue("enderecoCount");
         toRemove = input.getIntValue("i");
         for (int i = 1; i <= counter-1; i++) {
             if (i >= toRemove) {
                 input.setValue("logradouro_" + i, input.getValue("logradouro_" + (i+1)));
                 input.setValue("bairro_" + i, input.getValue("bairro_" + (i+1)));
                 //...
             }
         }
         counter--;
         input.setValue("enderecoCount", new Integer(counter));
         return SUCCESS;
     }
     
 }
 


Bom, é isso. O que achou?

Você sabe se tem uma maneira de colocar o contador sem criar a variável i no JSP?

Outro problema é que não posso utilizar o filtro de validação, pois ele é inicializado com a quantidade de campos fixa, acho que terei de fazer a validação diretamente na Action.


André Delorme
pauloperes


[Avatar]

Joined: 07/11/2005 13:56:45
Messages: 41
Offline

Olá a todos,

Galera também estou tendo problemas com Pais/Estado/Cidade. André legal a sua solução, mas me diz uma coisa, a lista de cidades sempre ficará em um List, ou seja, vai ficar o tempo todo na memória, isto não seria muito custoso?

Ah, consegui fazer isto somente com dois níves usando a tag <mtw:list> mesmo, porém quando adciono mais um nivel, que no caso seria a cidade, quando dou o reload, a lista de estados fica vazia, conforme post:

[url]
http://forum.mentaframework.org/posts/list/110.page
[/url]

Valeu,

Paulo
[Email] [MSN]
 
Forum Index -> Comentários Gerais
Go to:   
Powered by JForum 2.1.6 © JForum Team