Criar Combo Dinâmico em Ajax com jQuery + PHP

Listando Paises, Estados, Cidades e Bairros

Após usar extensivamente este recurso que vou apresentar aqui decidi compartilhar como eu procedo para obter tal resultado.

OBS.: Considero aqui que você já tenha baixado e instalado a biblioteca jQuery (usei a versão 1.3.2).

Neste exemplo vou utilizar quatro tabelas no banco de dados:

Mãos à obra!

Para organizar nosso trabalho, e como isto deve ser testado primeiro, vamos então criar um diretorio em nosso servidor chamado “teste-combo”.

Feito isto, crie 3 arquivos:

  • index.php
  • combo.js
  • localizacoes.php

[ index.php ]

<head>
  <script src="jquery-1.3.2.min.js"></script>
  <script src="combo.js"></script>
  <style>
    label {
      display:block;
    }
    label span {
      font-weight:bold;
      display:block;
    }
    select {
      width:150px;
    }
  </style>
</head>
<body>
  <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    <h1>Localizações</h1>
    <label><span>País:</span>
      <select name="pais" id="pais"></select>
    </label>
    <label><span>Estado:</span>
      <select name="estado" id="estado"><option value="0">--Primeiro o País--</option></select>
    </label>
    <label><span>Cidade:</span>
      <select name="cidade" id="cidade"><option value="0">--Primeiro o Estado--</option></select>
    </label>
    <label><span>Bairro:</span>
      <select name="bairro" id="bairro"><option value="0">--Primeiro a Cidade--</option></select>
    </label>
    <br />
    <label><input type="submit" value="Procurar"  />
  </form>
  <?php
  if ( $_POST ) {
    print '<pre>';
    print_r ( $_POST );
    print '</pre>';
  }
  ?>
</body>
</html>

OBS.: Eu não usei DOCTYPE ou outras tags e atributos HTML pois o objetivo é puramente ensinar como utilizar o recurso de combo dinâmico, por isto sinta-se à vontade de modifiicar como desejar. No arquivo acima, incluímos a biblioteca jQuery antes de qualquer arquivo, do contrário ela não funciona. Depois colocamos nosso arquivo combo.js. Criei um formulário com quatro SELECT’s respectivamente na ordem das localizações. Vamos ao nosso arquivo combo.js [combo.js]

 



  /*

   * Autor: Gilberto Albino
   * Data: 31/03/2009
   * Apaga isto por favor, hehe :D
   */
  jQuery(document).ready(
  function()
  {
    /*
     * Chamamos aqui a função que vai controlar os campos.
     * Desta forma, caso você precise repetir o combo dinâmico
     * basta trocar os ID's dos SELECT's
     */
    comboDinamico("pais", "estado", "cidade", "bairro");
    // suposição de segundo bloco de selects
    // comboDinamico("pais_cliente", "estado_cliente", "cidade_cliente", "bairro_cliente");
  }
);

  /*
   * função para carregar uma lista dinâmica
   */
  comboDinamico = function(pais, estado, cidade, bairro) {
    /*
     * Variáveis que precisamos pegar
     * Usamos getElementById() pois é assim que conseguiremos
     * passar o elemento por variável para jQuery
     */
    var pais   = document.getElementById(pais);
    var estado = document.getElementById(estado);
    var cidade = document.getElementById(cidade);
    var bairro = document.getElementById(bairro);
    /*
     * Carregamos a lista automaticamente quando a página carrega
     */
    $(pais).load('localizacoes.php?tipo=pais');

    /*
     * Populamos o combo dos estados quando trocamos um valor no pais
     * Os próximos blocos serão similares quanto à validação pelo valor igual à zero
     */

    $(pais).change(
    function() {
      if($(this).val() == 0) {
        alert('Você precisa informar um PAÍS!');
        $(this).focus();
      } else {
        $(estado).load('localizacoes.php?tipo=estado&amp;pais=' + $(this).val());
      }
    }
  );

    /*
     * Populamos o combo das cidades quando trocamos um valor no estado
     */

    $(estado).change(
    function() {
      if($(this).val() == 0) {
        alert('Você precisa informar o ESTADO!');
        $(this).focus();
      } else {
        $(cidade).load('localizacoes.php?tipo=cidade&amp;estado=' + $(this).val());
      }
    }
  );

    /*
     * Populamos o combo dos bairros quando trocamos um valor na cidade
     */
    $(cidade).change(
    function() {
      if($(this).val() == 0) {
        alert('Você precisa informar a CIDADE!');
        $(this).focus();
      } else {
        $(bairro).load('localizacoes.php?tipo=bairro&amp;cidade=' + escape($(this).val()));
      }
    }
  );

    /*
     * Uma validação simples só para garantir que não escolher um valor nulo
     */
    $(bairro).change(
    function() {
      if($(this).val() == 0) {
        alert('Você precisa informar o BAIRRO!');
        $(this).focus();
      } else {
        return true;
      }
    }
  );
  }

Como você pode notar eu comentei um pouco o código.

Mas só pra explicar rapidinho.

A cada alteração que realizamos num select ele carrega o arquivo “localizacoes.php” levando o tipo de consulta através da função load() da jQuery.

Vamos ver como ficou nosso arquivo localizacoes.php.

[localizacoes.php]

  

<?php
/*
* Bloco para testar a conexão
*/
try {
  /*
* Usei o banco mysql com o PDO.
* Se você estiver usando um servidor que não possua acesso ao PDO
* Ou não saiba como instalar o PDO, a lógica para trocar por funções mysql ou mysqli
* são visivelmente fáceis.
  */


  /*
* Variáveis de conexao
  */
  $servidor = 'localhost';
  $usuario = 'root';
  $senha = '';
  $banco = 'COLOQUE SEU BANCO AQUI';

  $con = new PDO( "mysql:host={$servidor};dbname={$banco}", $usuario, $senha );
  $con->query ( 'SET NAMES utf8' );
  /*
* Através deste bloco vamos alterar nossas consultas dinâmicas
*
* $sql = consulta própria do tipo
* $option = titulo que aparece no primeiro option da listagem
* $string = auxiliador da busca de resultados
  */

  switch ( $_GET['tipo'] ) {
    case 'pais' :
      $sql = "SELECT * FROM dados_paises WHERE status = 1";
      $option = 'o Pais';
      $string = 'iso3';
      break;
    case 'estado' :
      $sql = sprintf ( "SELECT * FROM dados_estados WHERE iso3 = '%s' AND status = 1", $_GET['pais'] );
      $option = 'o Estado';
      $string = 'uf';
      break;
    case 'cidade' :
      $sql = sprintf ( "SELECT * FROM dados_cidades WHERE uf = '%s'", $_GET['estado'] );
      $option = 'a Cidade';
      $string = 'nome';
      break;
    case 'bairro' :
      $sql = sprintf ( "SELECT * FROM dados_bairros WHERE cidade = '%s'", utf8_encode ( $_GET['cidade'] ) );
      $option = ' o Bairro';
      $string = 'nome';
      break;
  }
  /*
* Executamos o SQL aqui
  */
  $consulta = $con->query ( $sql );

  /*
* Iniciamos o resultado como null
  */
  $resultado = null;

  /*
* O primeiro option que vai aparecer já com o titulo dinâmico a partir de $option
  */

  $resultado = sprintf (
      '<option value="%s">Escolha %s</option>',
      0,
      $option
  );

  /*
* Um espaçador pra ficar elegante
  */

  $resultado .= sprintf (
      '<option value="%s">- - - - - - - - - - - - -</option>',
      0
  );

  /*
* Buscamos os resultados usando $c->string para identificar o ID dinamico pois varia, no caso temos iso3, uf, nome e nome
  */
  while ( $c = $consulta->fetch ( PDO::FETCH_OBJ ) ) {
    $resultado .= sprintf (
        '<option value="%s">%s</option>',
        $c->$string,
// o campo nome é comum a todos
        $c->nome
    );
  }

  /*
 * Imprimimos o resultado
  */
  print $resultado;

} catch ( Exception $e ) {

  /*
   * Se não aparecer nada é porque a conexao falhou :(
   */
  return null;
}
?>

Como você pode ver o código também está todo comentado .

Não há muito misterio nisto tudo, o que é preciso é uma boa lógica .

Para testar o bairro use a seguinte sequencia < strong > Brasil->Santa Catarina->Balneario Camboriu < strong >

Tente criar outras situações de combo dinâmico para estimular seu raciocínio .

39 comentários sobre “Criar Combo Dinâmico em Ajax com jQuery + PHP”

  1. Estanho, porque eu fiz ele no IE.
    E foi testado em IE6, IE7, IE8, FF 2, FF3, Opera 9.3, Safari 3, Netscape e Chrome.

    E outra coisa a se notar que ? o jQuery quem trata o AJAX e ele faz perfeitamente em todos os IE6++, ent?o o problema deve ser com a vers?o de seu navegador.

    Veja na busca deste site:
    http://www.himoveis.com

    ? a mesma coisa! E funciona perfeitamente.
    Se n?o funcionar no seu verifique se o javascript est? habilitado para seu navegador.

  2. parabens pela pagina, de longe a mais organizada, bem, problema ? q ando com dificuldades pra fazer seu exemplo funcionar, nao consigo instalar, habilitar esse PDO, reviro foruns e mais foruns e nao consegui.. Se poder me dar uma mao agrade?o. abra?os at

  3. Bom, Daniel.
    Em rela??o ao PDO a habilita??o do mesmo ? simples demais.
    Voc? precisa estar rodando o PHP 5 ou superior,
    caso contr?rio n?o vai rolar mesmo, pois o PHP 4 n?o tem suporte ao PDO, entretanto existe uma classe que emula o PDO para PHP 4 neste link http://www.phpclasses.org/browse/package/2572.html

    Caso, este n?o seja seu caso,
    basta procurar no arquivo php.ini de seu PHP as linhas:
    ;extension=php_pdo.dll
    e
    ;extension=php_pdo_mysql.dll

    E retirar o ponto e v?rgula inicial de ambos.
    Ai voce reinicia o apache e j? vai funcionar.

  4. Resolvido problema, valeu pelo apoio, foi um pouco de azar e falta de aten??o, pra falar a verdade esses estao sendo os maiores problemas desde que comecei a mecher com constru??o web, vale destacar mais uma vez a linha

    “Para testar o bairro use a seguinte sequencia Brasil->Santa Catarina->Balneario Camboriu”

    Valeu, abra?os e novamente parabens pelo seu trabalho.

  5. Sou fraco ainda nesse lance de programa??o, por isso pesso a ajuda de voc?s. No final do resultado, ou no momento de apertar o bot?o, ou no momento que seleciona a ?ltima tabela, como eu crio um link para uma linha espec?fica de uma das tabelas?

  6. Cara, muito show esse teu exemplo… mas eu tow precisando de uma rela??o completa dos estados e cidades de todos os pa?ses…

    Tu saca onde posso achar essas informa??es, mesmo que seja pra catar na m?o mesmo??

  7. Bom dia…..n?o manjo muito de php, mas encontrei seu artigo e curti demais!
    Mas ao enviar a consulta, ? exibido em baixo do “combo” uma mensagem mostrando o array que foi selecionado e n?o mostra o resultado dos bairro…Pq?

    At? mais e parabens pelos artigos
    Francisco

  8. case ‘tipoimovel’ :

    $sql = sprintf(“SELECT * FROM imoveis WHERE cidade=’%s’ AND bairro = ‘%s’ AND “, utf8_encode($_GET[‘bairro’], utf8_encode($_GET[‘cidade’])));
    $option = ‘ o Tipo’;
    $string = ‘tipo’;
    break;

    Como seria para um outro selec que busca a cidade e e bairro ao mesmo tempo?

  9. Ola,
    Parab?ns pelo Post

    estou implementando este Combo em meu site e funcionou muito bem…

    porem.. ap?s mudar minhas urls para Amigaveis.. com

    Ex.
    RewriteEngine On
    RewriteRule ^cadastre-se\/?$ index.php?id=cad

    O combo parou de funcionar e abre a index no lugar do combo… muito estranho isso
    percebi tamb?m que tudo que pego via ajax e Jquery deu problema…

    entao o causador de tudo foi o .htaccess

    Teria alguma solu??o pro meu caso???

    preciso urgente.. ja ca?ei em tudo quanto foi canto e nao axo nada

    Pra ficar bem claro oque estou tentando dizer ? que..

    Quando Seleciono o PAIS

    ao inves de abrir os estados abre a pagina index dentro do select estados…

    A pagina index ? o site inteiro mesmo!..aff..rsrs muito loko isso…

    me ajudem alguem
    Obrigado!

    Leonardo

  10. queria saber como faria para ao selecionar todos os campos, ele me retornar um quinto valor que se encontra no banco de dados

    Ex. ao selecionar país, estado, cidade e bairro, ele consulte a base de dados e mostre abaixo todos os usuário que moram naquele endereço, por exemplo.

    Alguem pode me ajudar?

  11. Ola Gilberto,

    Seu script é fantástico, simples e prático de implementar… Mas ainda estou com um problema pequeno, vou te explicar:

    Imagine que meu último SELECT é na realidade uma lista de serviços. Quando o usuário executa o CHANGE desse select. O script precisa buscar o preço de venda desse serviço na base, e apresentá-lo em um input a seguir.

    Já procurei um exemplo similar na net, mas não sei como fazer isso com o jquery. Você pode me ajudar?

    Att
    Vinícius

  12. Gilberto boa tarde, pode me ajudar ? usei seu script e está funcionando perfeitamente ,preenche os combos tudo perfeito , utilizei $_POST para pegar os dados preenchidos e gravar no banco, porém ao gravar traz informações dos outros campos com por ex. ISO3, UF. como faço para gravar somente o que está selecionado nos combos?
    Obrigado

  13. query ( ‘SET NAMES utf8’ );
    /*
    * Através deste bloco vamos alterar nossas consultas dinâmicas
    *
    * $sql = consulta própria do tipo
    * $option = titulo que aparece no primeiro option da listagem
    * $string = auxiliador da busca de resultados
    */

    switch ( $_GET[‘tipo’] ) {
    case ‘pais’ :
    $sql = “SELECT * FROM dados_paises WHERE status = 1”;
    $option = ‘o Pais’;
    $string = ‘iso3’;
    break;
    case ‘estado’ :
    $sql = sprintf ( “SELECT * FROM dados_estados WHERE iso3 = ‘%s’ AND status = 1”, $_GET[‘pais’] );
    $option = ‘o Estado’;
    $string = ‘uf’;
    break;
    case ‘cidade’ :
    $sql = sprintf ( “SELECT * FROM dados_cidades WHERE uf = ‘%s'”, $_GET[‘estado’] );
    $option = ‘a Cidade’;
    $string = ‘nome’;
    break;
    case ‘bairro’ :
    $sql = sprintf ( “SELECT * FROM dados_bairros WHERE cidade = ‘%s'”, utf8_encode ( $_GET[‘cidade’] ) );
    $option = ‘ o Bairro’;
    $string = ‘nome’;
    break;
    }
    /*
    * Executamos o SQL aqui
    */
    $consulta = $con->query ( $sql );

    /*
    * Iniciamos o resultado como null
    */
    $resultado = null;

    /*
    * O primeiro option que vai aparecer já com o titulo dinâmico a partir de $option
    */

    $resultado = sprintf (
    ‘Escolha %s’,
    0,
    $option
    );

    /*
    * Um espaçador pra ficar elegante
    */

    $resultado .= sprintf (
    ‘- – – – – – – – – – – – -‘,
    0
    );

    /*
    * Buscamos os resultados usando $c->string para identificar o ID dinamico pois varia, no caso temos iso3, uf, nome e nome
    */
    while ( $c = $consulta->fetch ( PDO::FETCH_OBJ ) ) {
    $resultado .= sprintf (
    ‘%s’,
    $c->$string,
    // o campo nome é comum a todos
    $c->nome
    );
    }

    /*
    * Imprimimos o resultado
    */
    print $resultado;

    } catch ( Exception $e ) {

    /*
    * Se não aparecer nada é porque a conexao falhou 🙁
    */
    return null;
    }
    ?>

    Como tirar o PDO e ficar funcional?

    1. Olá, Breno. A intenção não era demonstrar a conexão com o PHP, mas como funciona o combo em jQuery. Pretendo modificar este post para uma versão sem DB. Mil desculpas!

  14. estou com um problema, No momento que eu seleciono o pais(Brasil), abaixo, no campo estado ele mostra os 2 primeiros options(Selecione o Estado) e( ————–), mas não mostra nenhum estado, ele só mostra os estados quando eu troco a string %s no case’estado’ por ‘BRA’… Se alguem puder me ajudar. GRATO desde já pelo post me ajudou muito!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *