Galeria, é o seguinte:
Tenho um formulário com algumas listas, input etc, estes são enviados pelo controller da seguinte forma:
@Restrito
@Get("/novo")
public void novoChamado(){
result.include("produtoList", produtoDAO.listaAtivos());
result.include("tipoSolicitanteList", tiposolicitanteDAO.listaAtivos());
result.include("motivoList", motivoDAO.listaAtivos());
result.include("ocorrenciaList", ocorrenciaDAO.listaAtivos());
result.include("clientesList", clientesDAO.listaAtivos());
result.include("centroCustoClienteList", centroCustoClienteDAO.listaAtivos());
}
OK, as listas são carregadas e populadas corretamente, mas há duas que são totalmente ligadas.
Uma é de Clientes e a próxima é do Centro de Custo do cliente, em uma relação de 1 para N.
Ai vem a dúvida, qual seria a melhor alternativa para que até que se selecione o cliente a lista de centro de custo fique desabilitada e só então seja populada apenas com os respectivos centros de custo deste cliente?
Vi alguns exemplos utilizando JSON , jQuery e Ajax, mas em sua grande maioria há apenas dois campos sendo retornados pelo controller.
Ajax é, sem dúvidas, a melhor forma de fazer isso. A não ser que essas listas sejam extremamente pequenas.
Assim vc não precisa incluir a lista de centros toda.
Use o ajax do jQuery…
Algo assim:
no on change da combo (imagino que seja uma combo) de clientes, você faz um ajax que passa como parâmetro o ID do cliente selecionado e no retorno recebe a lista de centros.
Dai é só limpar a combo e adicionar a lista como um option mesmo.
Vlw Rafael,
Agora o problema é o select não popula, mas não achei onde estou errando, segue abaixo o que estou usando:
Controller:
@Restrito
@Get
@Path ("/novo/buscaCentroCusto.json")
public void carregaCentroCusto(Long cliente){
List<CentroCustoCliente> centrocusto = centroCustoClienteDAO.listaCentroCustoCliente(cliente);
result.use(Results.json()).withoutRoot().from(centrocusto)
.serialize();
}
DAO:
public List<CentroCustoCliente> listaCentroCustoCliente(Long fkidCliente){
return this.session.createCriteria(CentroCustoCliente.class)
.add(Restrictions.eq("FKidCliente", fkidCliente))
.add(Restrictions.eq("Ativo", Boolean.TRUE))
.addOrder(Order.asc("NomeCentroCusto"))
.list();
}
e a View:
<select id="clienteDropdown">
<option value="">Selecione o Cliente...</option>
<c:forEach items="${clientesList}" var="cliente" >
<option value="${cliente.IDCliente}">${cliente.nomeCliente}</option>
</c:forEach>
</select>
<!-- Tags da table e divs-->
<select id="centrocustoDropdown" disabled="disabled">
</select>
<img id="loading" alt="Carregando" src="<c:url value="/imagens/Load.gif"/>"/>
<script>
$(function(){
$('#loading').hide();
$('#clienteDropdown').change(function(){
adjustCentroCusto();
}).change();
$('#loading').ajaxStart(function() {
$(this).show();
});
$('#loading').ajaxStop(function(){
$(this).hide();
});
});
function adjustCentroCusto() {
var clienteValue = $('#clienteDropdown').val();
var centrocustoSet = $('#centrocustoDropdown');
if (clienteValue.length == 0)
{
centrocustoSet.attr("disabled", true);
centrocustoSet.emptySelect();
}
else
{
centrocustoSet.attr("disabled", false);
$.getJSON('/novo/buscaCentroCusto.json', {
cliente : clienteValue
}, function(data) {
centrocustoSet.loadSelect(data);
});
}
}
(function($) {
$.fn.emptySelect = function() {
return this.each(function(){
if (this.tagName=='SELECT') this.options.length = 0;
});
}
$.fn.loadSelect = function(data) {
return this.emptySelect().each(function(){
if (this.tagName=='SELECT') {
var selectElement = this;
$.each(data,function(index,optionData){
var option = new Option(optionData.IDCentroCusto, optionData.CentroCusto +' - '+ optionData.nomeCentroCusto);
if ($.browser.msie) {
selectElement.add(option);
}
else {
selectElement.add(option,null);
}
});
}
});
}
})(jQuery);
O estranho é que o no evento change no clienteDropdown, ao lado do select centrocustoDropdown deveria mostrar o gif de loading enquanto o ajax estivesse rodando, mas o mesmo nem é apresentado, apesar do select abaixo deixar de ficar desabilitado e ficar ativo apesar de estar vazio.
Alguém sabe o que pode ser ?
Galera,
Acho que sei o pq não popula, mas não sei como resolver.
Usando o console na hora da chamada do json, retorna status 404:
Tem um r, está chamando buscaCentroCustro e é buscaCentroCusto
Foi mal ae, eu que digitei errado na resposta. Mas o erro está acontecendo com o “buscaCentroCusto.json” mesmo
roda a url do JSON no browser mesmo, vê o que retorna, olha o console, vê o que o vraptor está te falando.
o @Path tem esse .json no final?
Lucas,
Ajustei 3 coisas que estavam erradas pelo visto:
1º - .json no Path, mudei de @Get @Path("/buscaCentroCusto.json")
Para: @Get("/buscaCentroCusto")
2º - No get do JSON o path informado não chamava o Controller o qual o mesmo está, segue abaixo como era e como ficou:
Antes $.getJSON('<c:url value="/buscaCentroCusto"/>'
Depois $.getJSON('<c:url value="/infoChamados/buscaCentroCusto"/>'
3º - (conforme o Rafael tinha falado)Chamei a url do json no browser passando um parametro, (Chamada: http://localhost:8080/SRP/infoChamados/buscaCentroCusto?cliente=200) então vi que o mesmo estava esperando um parâmetro do tipo Long, enquanto eu mandava um do tipo Integer .
Blz todos os problemas acimas foram ajustados, pelo console o retorno do json é o seguinte(para a mesma chamada que tinha retornado erro):
[{"IDCentroCusto": 449,"CentroCusto": "1.1.169.01.01","NomeCentroCusto": "AtendeSimples_VOS Center","FKidCliente": 200,"CodExterno": 797,"Ativo": true}]
Mas então o select não popula.
o fato do select não popular agora é questão de ajustar o javascript que faz isso
Bom Galera, Vlw pelas respostas
Consegui achar o porque de não popular.
No Script que retorna os options populados inseri um if para validar o browser utilizado, conforme abaixo:
if ($.browser.msie){
selectElement.add(option);
}
else
{
selectElement.add(option,null);
}
Mas a partir da versão 1.9 do jQuery (a qual eu uso) foi descontinuado essa propriedade (http://api.jquery.com/jQuery.browser/) enfim … deixei da seguinte forma:
selectElement.add(option);
Agora popula corretamente.