[RESOLVIDO]Combo estado/cidade vraptor

45 respostas
M

Bem, estou procurando moh tempão como efetuar colocar um combo entre estado e cidade e de acordo com o estado, listar todas as cidades, tenho o metodo que chama todas as cidades passando o id do estado, já está funcionando direitim, mais nao sei fazer isso com jsp, infelizmente ainda venho de uma dependencia de JSF ;/ e queria saber se algum de vcs sabem como implementar isso com vraptor. basicamente estou querendo fazer o seguinte:

<select id="estadosSelect" name="pessoa.perfil.estado">
   <option>Selecione</option>
   <c:forEach items="${estados}" var="estado">
      <option value="${estado}">${estado.nome}</option>
   </c:forEach>
</select>

<select id="cidadesSelect" name="pessoa.perfil.estado.cidade">
   <option>Selecione</option>
   <c:forEach items="${cidades}" var="cidade">
      <option value="${cidade}">${cidade.nome}</option>
   </c:forEach>
</select>

de forma que ao passar o estado acima ele carregasse as cidades abaixo. mais nao faço a minima ideia de como fazer. e a maioria dos links que vi o pessoal dizendo onde tinha o material, os links estão off.

essa é um dos problemas que enfrento por ainda nao migrar totalmente para o vraptor.

45 Respostas

d34d_d3v1l

Fala cara,

eu também venho do JSF e realmente, ele facilita muito quando a gente trabalha com ajax e view em geral…
Mas peca muito no desempenho… Bom sobre o que vc quer fazer, eu acabei de ver um tópico legal
sobre isso… Foge do que você quer fazer, mas talvez te ajude:

M

vou olhar d34d, toda ajuda é bem vinda, é pq infelizmente estou tendo que entender Java Script, e tenho muito problemas em entender como o JS pega determinados valores. mais vou olhar sim e continuar olhando essa thread aqui para ver novas respostas.

Rafael_Guerreiro

Você precisa fazer isso com jQuery e ajax:
1: Inicalizar a combo de cidades vazia.

&lt;select id="cidadesSelect" name="pessoa.perfil.estado.cidade"&gt;
&lt;/select&gt;

2: Arrumar a combo de estados

&lt;select id="estadosSelect" name="pessoa.perfil.estado"&gt;  
   &lt;option&gt;Selecione&lt;/option&gt;  
   &lt;c:forEach items="${estados}" var="estado"&gt;  
      &lt;option value="${estado.id}"&gt;${estado.nome}&lt;/option&gt;  &lt;!-- // o value tem que ser o ID do estado... --&gt;
   &lt;/c:forEach&gt;  
&lt;/select&gt;

3: No quando a combo de estados mudar, deve fazer uma busca ajax para pegar os options da cidade.

$(document).ready(function(){
   $('#estadosSelect').on('change', function(){
      var self = $(this);
      var selecionado = self.val(); // pega o ID do estado
      $.ajax({
         url:'/url/para/a/action',
         data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.
         dataType:'json', // O Server vai retornar um JSON
         success:function(data){
            // Precisa transformar de json para objeto html
            var options = [];
            options.push(' &lt;option&gt;Selecione&lt;/option&gt; '); // colocando a primeira option...
            for (var i = 0; i &lt; data.length; i++) {
               options.push('&lt;option value="'+data[i].id+'"&gt;'+data[i].nome+'&lt;/option&gt;');
            }
            
            // Agora precisa juntar esses options dentro da combo de cidades
            $('#cidadesSelect').html(options.join(''));
         },
         error:function(){
            alert('erro');
         }
      });
   });
});

4: Criar a sua action que vai retornar um JSON com as cidades.

@Get("/url/para/a/action")
public void getCidades(Long estado) {
   List&lt;Cidade&gt; cidades = cidadeDao.getPorEstado(estado); // Carrega as cidades que estão nesse estado...
   result.use(Results.json()).withoutRoot().from(cidades).serialize(); // Transforma a lista em JSON
}
d34d_d3v1l

Perfect!
x]

Acho que da pra colocar '[Resolvido]'
no tópico ein ?

Boa Guerreiro !
x]

M

Antes de mais nada quero agradeçer pela ajuda de vcs, rapida e muito didática.

Rafael Guerreiro vou testar essa aplicação agora a noite, pq ja peguei outro modulo aqui, ai volto aqui para te responder. mais ficou bem detalhado dessa forma, axo que vai dar tudo certo

mas antes de tudo me tira uma duvida:

data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.

esse estado, ele veio de onde? do ${estado} ?

esse: get

@Get("/url/para/a/action")  
public void getCidades(Long estado) { 
...
//

precisa ser …/a/action.json") ? ou dessa forma acima mesmo?

Rafael_Guerreiro

Tem que entender o padrão de objetos do Javascript. Funciona assim:

var objeto = { atributo1 : 'valor 1', atributo2 : 123 };
Ou seja, isso:

{estado:selecionado}

é um objeto aonde o valor do atributo “estado” está na variável “selecionado”, que foi setada acima.
Repare na linha 4 do segundo passo, onde a gente arrumou a EL para pegar o ID do estado e não o toString de estado…

Quanto à segunda pergunta, o path do get não precisa, NESSE CASO, terminar com .json (fica ao seu critério)…

M

outra coisa: quando vc faz o:

var self = $(this);

o que vc está pegando com a variavel self ?

esse: data:{estado:selecionado}, //aqui tem que ser estado pq no getCIdades tbm é a variavel estado, é isso?

é pq tem public void getCidades(Long estado) // tem que ser esse mesmo nome aqui é?

Rafael_Guerreiro

Quando vc faz um evento dessa forma:

O jQuery coloca um valor na variável “this” (sim, this é uma variável no javascript). O valor é justamente o elemento que desencadeou essa ação.

Quando eu faço $(this), eu quero que o jQuery me retorne uma instancia jQuery desse elemento. Para isso, ele procura esse elemento no DOM da sua página e retorna a instancia.

Para que o jQuery não fique procurando o elemento no DOM toda vez que eu precisar ver alguma coisa nesse elemento, eu mando ele jogar nessa variável e ele só busca uma vez. Ficando mais rápido e menos custoso para o browser.

Rafael_Guerreiro

maaarkin:

esse: data:{estado:selecionado}, //aqui tem que ser estado pq no getCIdades tbm é a variavel estado, é isso?

é pq tem public void getCidades(Long estado) // tem que ser esse mesmo nome aqui é?

Exatamente!

M

Ok, mais tarde vou testar teu codigo direitim e com calma, pq alem de utilizar o codigo quero estudar e entender como funciona.

M

Rafael Guerreiro:
Quando vc faz um evento dessa forma:

O jQuery coloca um valor na variável “this” (sim, this é uma variável no javascript). O valor é justamente o elemento que desencadeou essa ação.

Quando eu faço $(this), eu quero que o jQuery me retorne uma instancia jQuery desse elemento. Para isso, ele procura esse elemento no DOM da sua página e retorna a instancia.

Para que o jQuery não fique procurando o elemento no DOM toda vez que eu precisar ver alguma coisa nesse elemento, eu mando ele jogar nessa variável e ele só busca uma vez. Ficando mais rápido e menos custoso para o browser.

Nesse caso aqui, esse this, é o OBJETO estado, ou nao?

Rafael_Guerreiro

Concordo com você! E vou te explicar tudo que eu conseguir…

Rafael_Guerreiro

maaarkin:
Rafael Guerreiro:
Quando vc faz um evento dessa forma:

O jQuery coloca um valor na variável “this” (sim, this é uma variável no javascript). O valor é justamente o elemento que desencadeou essa ação.

Quando eu faço $(this), eu quero que o jQuery me retorne uma instancia jQuery desse elemento. Para isso, ele procura esse elemento no DOM da sua página e retorna a instancia.

Para que o jQuery não fique procurando o elemento no DOM toda vez que eu precisar ver alguma coisa nesse elemento, eu mando ele jogar nessa variável e ele só busca uma vez. Ficando mais rápido e menos custoso para o browser.

Nesse caso aqui, esse this, é o OBJETO estado, ou nao?


Não confunda OBJETO com ELEMENTO… Quando vc faz ‘${estado}’ você está acessando o toString da instância (no Java), ou seja, o tomcat vai lá e procura alguma variável que se chame “estado” e aciona o toString dele. Quando a página é renderizada pelo browser o tomcat não tem mais ação nenhuma, tudo foi transformado em String.

O Javascript não tem acesso aos seus objetos, por isso ele trata tudo como string… Então, o this, é o ELEMENTO do select… Se vc usa o chrome e mandar ele imprimir o elemento assim:

console.log(this); Você vai ver que ele vai te mostrar o ELEMENTO select inteiro (inclusive os filhos, que são os options)…

M

bem, listando está, mais está caindo no error.

vou colocar como adaptei o metodo para esse exemplo Rafael.

Pagina:

<%@ page contentType="text/html; charset=UTF-8" %>

<script>
$(document).ready(function(){  
	   $('#estadosSelect').on('change', function(){  
	      var self = $(this);  
	      var selecionado = self.val(); // pega o ID do estado  
	      $.ajax({  
	         url:'/visitante/carregaCidades/',  
	         data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.  
	         dataType:'json', // O Server vai retornar um JSON  
	         success:function(data){  
	            // Precisa transformar de json para objeto html  
	            var options = [];  
	            options.push(' <option>Selecione</option> '); // colocando a primeira option...  
	            for (var i = 0; i < data.length; i++) {  
	               options.push('<option value="'+data[i].codigo+'">'+data[i].nome+'</option>');  
	            }  
	              
	            // Agora precisa juntar esses options dentro da combo de cidades  
	            $('#cidadesSelect').html(options.join(''));  
	         },  
	         error:function(){  
	            alert('erro');  
	         }  
	      });  
	   });  
	}); 
</script>

<div>
<form action="salvar" method="post">
   <fieldset>
     <legend>Adicionar Visitante</legend>
     
     <label for="nome">Rua:</label>
     <input id="nome" type="text" placeholder="nome" name="visitante.nome"/>
     
     <label for="rua">Rua:</label>
     <input id="rua" type="text" placeholder="rua" name="visitante.endereco.logradouro"/>
     
     <label for="descricao">estado:</label>
     <select id="estadosSelect" name="visitante.endereco.cidade.estado">  
	   <option>Selecione</option>  
	   <c:forEach items="${estadoList}" var="estado">  
	      <option value="${estado.codigo}">${estado.sigla}</option>  
	   </c:forEach>  
	 </select>
     
     <select id="cidadesSelect" name="visitante.endereco.cidade">  
	 
	 </select> 
     
     <br/>
     <button type="submit" class="btn">Salvar</button>
   </fieldset>
 </form>
</div>

meu controllador:

@Get("/visitante/carregaCidades/{codigo}")  
	public void carregaCidades(Long estado) {  
	   List<Cidade> cidades = this.cidadeRep.findCitiesFromState(estado); // Carrega as cidades que estão nesse estado...  
	   result.use(Results.json()).withoutRoot().from(cidades).serialize(); // Transforma a lista em JSON  
	}

estava analisando o codigo e no metodo nao é pra ser @Post nao?

Rafael_Guerreiro

@Get("/visitante/carregaCidades/{codigo}")Você está esperando uma variável “codigo” na sua URL…

Ou seja, a url ‘/visitante/carregaCidades/’ não existe. Por isso está errado. Existem 2 saidas:

  1. Mudar o nome da variável para estado e passar o valor na url:
// ...
$.ajax({    
             url:'/visitante/carregaCidades/' + selecionado,     // COLOQUEI O PARAMETRO AQUI.
             // data:{estado:selecionado}, // Remove essa linha
             dataType:'json',
//...

########### OU ###########

  1. Remove a variável na url e deixe TUDO como está.
M

vou testar aqui agora.

M

testei das duas formas e não deu veja como ficou da forma que testei agora:

<script>
$(document).ready(function(){  
	   $('#estadosSelect').on('change', function(){  
	      var self = $(this);  
	      var selecionado = self.val(); // pega o ID do estado  
	      $.ajax({  
	    	  url:'/visitante/carregaCidades/' + selecionado,  
	         //data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.  
	         dataType:'json', // O Server vai retornar um JSON  
	         success:function(data){  
	            // Precisa transformar de json para objeto html  
	            var options = [];  
	            options.push(' <option>Selecione</option> '); // colocando a primeira option...  
	            for (var i = 0; i < data.length; i++) {  
	               options.push('<option value="'+data[i].codigo+'">'+data[i].nome+'</option>');  
	            }  
	              
	            // Agora precisa juntar esses options dentro da combo de cidades  
	            $('#cidadesSelect').html(options.join(''));  
	         },  
	         error:function(){  
	            alert('erro');  
	         }  
	      });  
	   });  
	}); 
</script>
@Get("/visitante/carregaCidades/{estado}")  
	public void carregaCidades(Long estado) {  
	   List<Cidade> cidades = this.cidadeRep.findCitiesFromState(estado); // Carrega as cidades que estão nesse estado...  
	   result.use(Results.json()).withoutRoot().from(cidades).serialize(); // Transforma a lista em JSON  
	}
M

será que é porque estou usando Long?

Rafael_Guerreiro

Certo, vc testou, mas vc debugou? Descobriu o que está acontecendo?

Tente achar uma solução, caso não consiga, venha perguntar aqui.

M

primeiramente estou vendo logo se estava recebendo a lista de cidades do sql, e vi que nao estava, estou tentando logo encontrar o erro que está dando e volto a testar rafael.

M

Bem, vamos lá, corrigi a parte do hibernate onde ele me retorna corretamente a lista de cidades, até ae tudo bem, o que fiz agora foi colocar um breakpoint no metodo carregaCidades para ver pelo menos se está acessando o metodo, mais pelo que vi, se quer ele entra no metodo carregaCidades.

segue como está meu codigo.

@Get("/visitante/carregaCidades")
	public void carregaCidades(int estado) {  
	   List<Cidade> cidades = this.cidadeRep.findCitiesFromState(estado); // Carrega as cidades que estão nesse estado...  
	   result.use(Results.json()).withoutRoot().from(cidades).serialize(); // Transforma a lista em JSON  
	}

Obs: usei o firebug e pelo que vi, ele está pegando o Id corretamente, inclusive cheguei a criar uma pagina carregaCidades.jsp para ver se está ocorrendo tudo certo, mais pelo que vi coloquei o breakpoint no metodo e ele nao entra la.

<script>
$(document).ready(function(){  
	   $('#estadosSelect').on('change', function(){  
	      var self = $(this);  
	      var selecionado = self.val(); // pega o ID do estado  
	      $.ajax({  
	    	 url:'/visitante/carregaCidades/',//+ selecionado,  
	         data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.  
	         dataType:'json', // O Server vai retornar um JSON  
	         success:function(data){  
	            // Precisa transformar de json para objeto html  
	            var options = [];  
	            options.push(' <option>Selecione</option> '); // colocando a primeira option...  
	            for (var i = 0; i < data.length; i++) {  
	               options.push('<option value="'+data[i].codigo+'">'+data[i].nome+'</option>');  
	            }  
	              
	            // Agora precisa juntar esses options dentro da combo de cidades  
	            $('#cidadesSelect').html(options.join(''));  
	         },  
	         error:function(){  
	            alert('erro');  
	         }  
	      });  
	   });  
	}); 
</script>

não precisao ser @Post nao?

obs: está sempre aparecendo a mensagem de erro.

Rafael_Guerreiro

Não precisa ser POST. A sua action está anotada com @Get. Então, TEM que ser Get…

O problema é que a URL está errada. Na sua action não tem a ‘/’ no final e no ajax tem.

Outro problema, você deve considerar o contextPath para garantir essa chamada.

M

Rafael Guerreiro:
Não precisa ser POST. A sua action está anotada com @Get. Então, TEM que ser Get…

O problema é que a URL está errada. Na sua action não tem a ‘/’ no final e no ajax tem.

Outro problema, você deve considerar o contextPath para garantir essa chamada.

mais essa barra ae foi pq fui testando de varias formas e que esqueci tbm, mais acabei de testar corrigindo e nada, e quanto ao contextPath, nao sei como corrigir isso, visto que eu estou no /visitante/formulario.

mais o que estou encabulado é que nao está nem entrando no metodo.

Rafael_Guerreiro
M

testei como você falou e testei tambem

url:'"<c:url value="/visitante/carregaCidades/" />'+ selecionado,  
	         //data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.  
	         dataType:'json', // O Server vai retornar um JSON
@Get("/visitante/carregaCidades/{estado}")
	public void carregaCidades(int estado) {  
	   List<Cidade> cidades = this.cidadeRep.findCitiesFromState(estado); // Carrega as cidades que estão nesse estado...  
	   result.use(Results.json()).withoutRoot().from(cidades).serialize(); // Transforma a lista em JSON  
	}

e nada, nem entra no metodo, só cai no erro.

Rafael_Guerreiro

Pode mostrar o erro que o browser mostra para você?

M

opa, consegui entrar no metodo

coloquei da seguinte forma:

url:'<c:url value="/visitante/carregaCidades/" />'+ selecionado,    
             //data:{estado:selecionado}, // Passa a variável ao server. O nome do parâmetro tem que ser estado, pois foi o nome colocado aqui.    
             dataType:'json', // O Server vai retornar um JSON

tinha colocado uma " antes do <c:

M

aeeew, dessa forma consegui, vou avançar agora e ver como salvar o visitante no banco, resgatanto o id da cidade e do estado.

Rafael_Guerreiro

Marca lá como resolvido…

O mais importante é: você entendeu tudo ou tem alguma dúvida?

Lucas_Cavalcanti

é GET mesmo, o problema é que tem uma / no final
muda para

url:'/visitante/carregaCidades',
M

na verdade a url precisava do contextPath lucas, eu não sabia que podia colocar ou pior, que precisava. Mais é a url que vc passou msm, eu já consegui como havia falado mais agradeço por ter vindo ajudar.

estou tentando a partir desses códigos que vc e o rafael mostram estudar um pouco de javascript, jquery e o principal, vRaptor, por ele me disponibilizar um json já prontinho.

Fico grato.

M

rafael, aproveitando o uso do topico que foi dada uma senhora aula de jquery, você me auxiliou informando o seguinte:

onde esse id vem de um combobox, estou tentando migrar essa estrutura para um checkbox, como posso capturar a ação de marcar e desmarcar o checkbox? estou procurando a api aqui mais nao tou encontrando algo relacionado,

estava procurando algo no tipo

$('#estadosSelect').on('check', function() - para marcar.

$('#estadosSelect').on('uncheck', function() - para desmarcar

mais ainda não encontrei nada do tipo, se poderem auxiliar, fico grato.

Lucas_Cavalcanti

vc pode fazer isso:

$('#id-do-checkbox').on('click', function() {
    if ($(this).is(':checked')) {
       //...
    } else {
       //...
    }
});
M

Lucas, tenho uma dúvida um tanto quanto chata que é a seguinte, eu preciso fazer um forEach na visão onde eu preciso povoar a varios input Radio com as devidas Permissões

basicamente o seguinte:

[ ] Alterar
[ ] Visualizar
[ ] Nenhuma

porem esse determinado grupo possui a permissão Alterar, e queria que mostrasse da seguinte forma:

[X] Alterar
[ ] Visualizar
[ ] Nenhuma

ou seja, que ele mostrasse já marcado, é possível fazer isso? primeiramente pensei em utilizar um c:if, mais só sei usar o atributo eq do c:if, ele possui algo como um contains?

e outra, com a opção input Radio o radio só é desmarcado quando outro radio com mesmo name é desmarcado só que esse meu nao terá o name, ele efetuará um ajax dependendo da ação de clicar ou não no radio.

Lucas_Cavalcanti

para o c:if vc pode usar o ${fn:contains(lista, ‘PERMISSAO’)}

para os radios, vc precisa colocar um name, mesmo que não for usar pra nada.

M

vou começar a criar a tela aqui e posto a duvida aqui novamente, mais minha duvida por enquanto será mesmo na questão do ${fn:contains(lista, ‘PERMISSAO’)} .

quando eu montar a estrutura ficará melhor para você me auxiliar, quando eu montar a tela mostro aqui.

M

No caso, se a condição for verdadeira, como fazer com que o radio aparecer já marcado?

Lucas_Cavalcanti

só adicionar o atributo checked no input.

M

lucas é possível isso:

${usuario.ativo ? ‘’ : ‘inativo’}

com c:if test…

?

Lucas_Cavalcanti

é possivel isso:

<input type="checkbox" ... ${usuario.ativo ? '' : 'checked'}>

<span>${usuario.ativo ? '' : 'inativo'}</span>

não precisa do c:if :wink:

M

com jstl eu posso usar ${usuario.nome == “MeuNome” ? ‘’ : ‘inativo’}

ou uso algum equals depois de .nome?

Lucas_Cavalcanti

use eq :wink:

M

Lucas, peguei esse contexto para entender o contains.

<c:set var=“theString” value=“I am a test String”/>

<c:if test="${fn:contains(theString, ‘test’)}">

Found test string

mais minha questão é o seguinte fui ler a documentação e está assim:

The fn:contains() function has following syntax:

boolean contains(java.lang.String, java.lang.String);

ou seja, ele pede uma String para comparar com uma string.

Minha classe Grupo tem um Set lista

e no metodo editar eu retorno um objeto Grupo para a visão, essa coleção eu acesso via {grupo.permissoes} como eu poderia verificar se uma string está contida dentro dessa coleção?

a forma seria a mesma? ou seja ${fn:contains({grupo.permissoes}, ‘nomeDaString’)} ?

Lucas_Cavalcanti

seria assim:

${fn:contains(grupo.permissoes, 'nomeDaString')}

se não funcionar, inverte os parametros :wink:

M

funcionou sim, ficou da seguinte forma:

<c:forEach var="permissao" items="${permissoes}"> <c:if test = "${permissao eq 'Funcionario_Alterar'}"> <input type="radio" class="radio" style="margin-left: 10px;" name="permissao.permFuncionario" value="${permissao}" ${fn:contains(grupo.permissoes, permissao) ? 'checked="checked"' : ''}>Alterar </c:if> <c:if test = "${permissao eq 'Funcionario_Visualizar'}"> <input type="radio" class="radio" style="margin-left: 10px;" name="permissao.permFuncionario" value="${permissao}" ${fn:contains(grupo.permissoes, permissao) ? 'checked="checked"' : ''}>Visualizar </c:if> <c:if test = "${permissao eq 'Funcionario_Nenhuma'}"> <input type="radio" class="radio" style="margin-left: 10px;" name="permissao.permFuncionario" value="${permissao}" ${checked ? 'checked="checked"' : ''} ${fn:contains(grupo.permissoes, permissao) ? 'checked="checked"' : ''}>Nenhuma </c:if> </c:forEach>

Criado 30 de abril de 2013
Ultima resposta 20 de jun. de 2013
Respostas 45
Participantes 4