(RESOLVIDO) VRaptor com forms compostos (bean.List's)

12 respostas
xdraculax

Olá pessoal!

O problema é o seguinte:

Tenho um bean onde, um de seus atributos é um List, então, no form de cadastro desse bean eu gostaria de adicionar/remover/editar itens desse List.

A dúvida é sobre como isso é feito em sistemas com arquitetura do tipo ‘action’ como o VRaptor:

-Na primeira abordagem, faço as modificações na List através de requisições AJAX ao Controller que adiciona/remove/edita itens diretamente no bean, e renderizo novamente a view.
-Na outra abordagem, faço tudo na view com JavaScript/HTML, e resolvo tudo na hora do POST. (é a mais botina, mas gera um código cabuloso na view)

Gostaria de saber o que normalmente vocês usam, ou se nem fazem nenhuma dessas duas coisas.
Obrigado,

12 Respostas

Rafael_Guerreiro

Eu gosto muito de usar AJAX para incluir, remover, editar, listar e detalhar os registros. Acho que dá uma sensação de maior velocidade para o usuário.

Quanto ao tratamento, eu costumo fazer o básico na view (como garantir que os campos obrigatórios sejam preenchidos), validar algumas coisas no servidor (como tamanho de alguns campos) e deixar que o banco valide o restante (como integridade dos dados).

Lucas_Cavalcanti

eu costumo fazer essa segunda opção…

não é um código tão difícil de fazer, principalmente se vc usar um template javascript como o mustache.js ou o handlebars.

xdraculax

Obrigado pelas respostas galera.

Me sinto tentado a optar pela segunda opção pelo fato de que a aplicação será bastante utilizada remotamente inclusive por usuários com conexões de baixa qualidade.

Porém o ponto fraco é que essa abordagem gera esse tipo de código:

(Essa página lista o cadastro de uma fatura que possui n parcelas. O usuário pode adicionar/remover/editar essas parcelas.)

function adicionarItem(){
			$(
				'<tr> <br />' +
					'<td><input type="hidden" name="fatura.parcelas['+$('#parcelas tr').length+'].id" /></td> <br />' +
					'<td><input type="text" name="fatura.parcelas['+$('#parcelas tr').length+'].dataVencimento" class="data" /></td> <br />' +
					'<td><input type="text" name="fatura.parcelas['+$('#parcelas tr').length+'].valor" /></td> <br />' +
				'</tr>	<br />'
			).appendTo('#parcelas'); 
			
			inicializarComponentes();
		}

Mais adiante na mesma página, temos o código com a JSTL que irá listar os itens:

<c:forEach items="${fatura.parcelas}" var="i" varStatus="s">
				<tr>
					<td><input type="hidden" name="fatura.parcelas[${s.index}].id" value="${fatura.parcelas[s.index].id}" /></td>
					<td><input type="text" name="fatura.parcelas[${s.index}].dataVencimento" value="${fatura.parcelas[s.index].dataVencimento}"  class="data"/></td>
					<td><input type="text" name="fatura.parcelas[${s.index}].valor" value="${fatura.parcelas[s.index].valor}"/></td>
				</tr>		
			</c:forEach>

Esse é o problema, duplicidade no código, e fora a qualidade do HTML que é gerado que é bem ruin porque perde a identação (bem, isso é até aceitável ^^).
Dei uma olhada no conceito de “teamplating” com javascript, mas não vi como isso poderia me ajudar a solucionar esse tipo de problema.

Obrigado

Lucas_Cavalcanti

vc pode ao invés de criar as linhas via jstl, vc cria via javascript, usando o mesmo template.

algo assim:

<c:forEach items="${fatura.parcelas}" var="i" varStatus="s">  
    <tr data-index="${s.index}" data-id="${...}" data-datavencimento="...." data-valor="...">  
    </tr>       
</c:forEach>

e no javascript vc usa esses atributos pra popular o template, e criar a linha de verdade.

xdraculax

Lucas Cavalcanti:
vc pode ao invés de criar as linhas via jstl, vc cria via javascript, usando o mesmo template.

algo assim:

<c:forEach items="${fatura.parcelas}" var="i" varStatus="s">  
    <tr data-index="${s.index}" data-id="${...}" data-datavencimento="...." data-valor="...">  
    </tr>       
</c:forEach>

e no javascript vc usa esses atributos pra popular o template, e criar a linha de verdade.

Isso não quebraria quando a List estiver vázia?

Lucas_Cavalcanti

Só vai ficar uma tabela vazia, sem nenhum tr

P

Uso a segunda opção e sobre o codigo use jquery.

xdraculax

Olá galera.

Bom, não saquei muito bem como ia usar essas lib’s de template com javascript. Vejam o que acabei fazendo:

Código JTSL que itera através dos ‘impostos’ da compra:

<c:forEach items="${compra.impostos}" var="i">
       <script> adicionarImpostoACompra('${i.id}','${i.imposto.id}'...); </script>
</c:forEach>

E o código que de fato adiciona a linha à tabela:

function adicionarImpostoACompra(idItem,idImposto,codigo,descricaoImposto,tarifaAplicada){
      $('<tr id="imposto'+idItem+'">' +
      ...
      ).appendTo('#impostosAplicados');

Bom, o código HTML gerado não ficou lá essas coisas, mas a parte do VRaptor ficou show, e o código escrito também ficou bom ao meu ver. Os templates seriam algo melhor que isso?

Lucas_Cavalcanti

isso funciona sim… o template facilitaria um pouco essa concatenação de strings…

xdraculax

Bom, coloquei o esquema do templating com o http://handlebarsjs.com/:

Primeiro, declarei o template em uma sessão de script:

<script id="template-parcela" type="text/x-handlebars-template">
	<tr id="parcela{{idItem}}">
		<td><input type="hidden" value="{{idItem}}" name="fatura.parcelas[{{idItem}}].id" /></td>
                ...
	</tr>
</script>

Depois, eu compilei o template (é recomendado pela documentação do handlebars, principalmente para dispositivos móveis):

var templateParcela = Handlebars.compile($("#template-parcela").html());

Por último, é só adicionar as linhas à tabela:

<c:forEach items="${fatura.parcelas}" var="i" varStatus="s">
      <script>adicionarParcela("${i.id}","${i.dataVencimento}","${i.valor}");</script>
</c:forEach>

Realmente o código ficou mais organizado.

Lucas_Cavalcanti

legal! funcionou direitinho?

dica: vc pode colocar o fora do foreach

xdraculax

Funcionou sim cara, ficou show. O código HTML gerado também é bem mais decente.

E com relação ao script, boa dica.

Vlw!

Criado 18 de setembro de 2012
Ultima resposta 26 de set. de 2012
Respostas 12
Participantes 4