Cargando



Grocery Crud PHP - Combo Box / Dropdown relacionados y dependientes

Grocery CRUD de es una biblioteca de código abierto que permite desarrollar crud rápido y con pocas lineas de código. Grocery CRUD permite crear una aplicación estable, completa y elegante a la vista en muy poco tiempo. Entra, aprende y disfruta con el ejemplo que muestro.


ago 28 2015 11:55
Profesional
ene 21 2016 14:59

Habíamos mencionado en otro tutorial como comenzar el desarrollo con Grocerycrud para Codeigniter PHP, a continuación veremos como hacer que varios combo box o dropdown están relacionados entre si y dependen uno de otro.

 

Veamos un ejemplo completo con una Base de datos denominada Inmobiliaria, la estructura será la siguiente:

 

Estructura de tabla para la tabla `inmuebles`

CREATE TABLE IF NOT EXISTS `inmuebles` (

  `idinmueble` int(11) NOT NULL,
  `idusuario` int(11) DEFAULT NULL,

  `fechaAlta` date DEFAULT '0000-00-00',
  `idtipoimueble` int(6) DEFAULT '0',

  `precio` decimal(10,2) DEFAULT '0.00',
  `descripcion` text,

  `idprovincia` int(10) DEFAULT NULL,
  `idlocalidad` int(10) DEFAULT NULL,

  `direccion` varchar(150) DEFAULT NULL,
  `foto` varchar(255) DEFAULT NULL,

  `disponible` enum('Si','No') DEFAULT NULL
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;


CREATE TABLE IF NOT EXISTS `localidades` (
  `idlocalidad` int(11) NOT NULL,

  `localidad` varchar(200) DEFAULT NULL,
  `idprovincia` int(11) DEFAULT '0'

) ENGINE=MyISAM AUTO_INCREMENT=3604 DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `usuarios` (
  `idusuario` int(11) NOT NULL,

  `nombre` varchar(150) NOT NULL DEFAULT ''
) ENGINE=MyISAM AUTO_INCREMENT=161 DEFAULT CHARSET=latin1;


CREATE TABLE IF NOT EXISTS `tipoinmueble` (

  `idtipoinmueble` int(6) NOT NULL,
  `tipoinmueble` varchar(150) NOT NULL DEFAULT ''

) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `provincias` (
  `idprovincia` int(11) NOT NULL,

  `provincia` varchar(255) COLLATE latin1_spanish_ci DEFAULT NULL
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci;
Podemos realizar mediante phpmyadmin un diagrama de relaciones que será el siguiente:

grocery.jpg

 

En el tutorial anterior vimos como instalar y configurar Grocerycrud, aquÍ crearemos la aplicación, creamos el controlador Inmo.php

<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class Inmo extends CI_Controller {

function __construct()
{

  parent::__construct();

  $this->load->database();
  $this->load->helper('url');

  $this->load->model('grocery_crud_model');
  $this->load->library('Grocery_CRUD');


}


public function index()

{
 

   $crud = new grocery_CRUD();
  $crud->set_theme('flexigrid');

   $crud->set_table('inmuebles');
  

  
  $output = $crud->render();

  $this->load->view('inmolista', $output);
} } ?>
A continuación creamos la vista que llamaremos listainmo.php, los archivos CSS y JQuery los tomará de la configuración de Grocery Crud por ello aquí solo los listamos:
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php

foreach($css_files as $file): ?>
<link type="text/css" rel="stylesheet" href="<?php echo $file; ?>" />

<?php endforeach; ?>
<?php foreach($js_files as $file): ?>

<script src="<?php echo $file; ?>"></script>
<?php endforeach; ?>


<body>

<div style='height:20px;'></div> 
    <div>

  <?php echo $output; ?>

    </div>
</body>

</html>
El resultado al ejecutar la web en un navegador http://localhost/pro...os/inmobi/Inmo/

 

grocery2.jpg

 

Podemos observar que los id muestran números en lugar de datos esto es porque las tablas no están relacionadas para relacionarlas haremos los siguiente, en el controlador debajo de set_table indicaremos.

$crud->set_relation(‘idarelacionar’,’tablaarelacionar’,’campoamostrar’);
De ejemplo quiero mostrar el nombre de usuario de la tabla usuario, con el id de usuario de la tabla inmuebles entonces deberé escribir el siguiente código:
$crud->set_relation('idusuario','usuarios','nombre');
Como resultado de ejecutar veremos que en lugar un numero en idusuario nos muestra el nombre.

 

grocery3.jpg

 

A continuación vamos a relacionar los ademas campos, provincia y localidades.

$crud->set_relation('idtipoinmueble','tipoinmueble','tipoinmueble');

$crud->set_relation('idprovincia','provincias','provincia');
$crud->set_relation('idlocalidad','localidades','localidad');
Después de ejecutar veremos los id con su respectiva relación:

 

grocery4.jpg

 

En el caso de imágenes deberemos usar

$crud->set_field_upload(campo,'rutadeimagen');
Entonces utilizaremos el mismo directorio de Grocery crud para guardar imágenes
$crud->set_field_upload('foto','assets/uploads/files');
Aunque podemos mostrar en el listado los campos y combos relacionados, no son dependientes, queremos que al seleccionar una provincia en el combo de provincias se active en forma automática el de localidades y se llene con las localidades de esa provincia, ademas queremos que esa relación se mantenga cuando añadimos un inmueble o cuando lo editamos.

 

grocery5.jpg

 

Para hacer los combos dependientes utilizaremos una función callback. Un callback o devolución de llamada es una alternativa al polimorfismo, esto fue un tema que tratamos en otro tutorial para saber implementar las clases:

 


 

Clases y Polimorfismo con PHP

 

 

Donde a una función se le asigna como parámetro otra función, una función de nivel inferior. Un callback puede actuar cuando se añade un registro o cuando se modifica. Este método permite una gran reutilización de código.

 

La sentencia de un callback puede ser la siguiente en el controlador.

$crud->callback_add_field(‘nombrecallback’, Array(parametros));
En este caso el callback sera idlocalidad y la función sera cbklocalidades
$crud->callback_add_field('idlocalidad', array($this, 'cbklocalidades'));

$crud->callback_edit_field('idlocalidad', array($this, 'cbklocalidades'));
A continuación creamos la funcion cbklocalidades que sera nuestro callback invocado cuando agregemos o editemos un registro.
//Callback que genera el combo idlocalidades


function cbklocalidades()

{

//creamos el combo
$combo = '<select name="idlocalidad" class="chosen-select" data-placeholder="Seleccionar localidad" style="width: 300px; display: none;">';

$fincombo = '</select>';

//Tomamos el id de inmueble si se enviocomo parámetro por url
  $idinmuebleurl = $this->uri->segment(4);


//Verificamos la operacion que estamos haciendo si agregamos o editamos

  $crud = new grocery_CRUD();
  $estado = $crud->getState();


  //Si estamos editando y el id de inmueble no es vació

  if(isset($idinmuebleurl) && $estado == "edit") {
   //consultamos la provincia y la localidad actual del inmueble

   $this->db->select('idprovincia, idlocalidad')
      ->from('inmuebles')

      ->where('idinmueble', $idinmuebleurl);
     

   $db = $this->db->get();
   $row = $db->row(0);

   $idprovincia = $row->idprovincia;
   $idlocalidad = $row->idlocalidad;

  
   //Cargamos el combo con todas las localidades de la pronvincia

   $this->db->select('*')
      ->from('localidades')

      ->where('idprovincia', $idprovincia);

   $db = $this->db->get();


  

//Si ecnontramos el id de localidad actual lo ponemos como selecionado
//sino seguimos cargando las demas localidades


   foreach($db->result() as $row):

    if($row->idlocalidad == $idlocalidad) {
     $combo .= '<option value="'.$row->idlocalidad.'" selected="selected">'.$row->localidad.'</option>';

    } else {
     $combo .= '<option value="'.$row->idlocalidad.'">'.$row->localidad.'</option>';

    }
   endforeach;

  
//Devolvemos el combo cargado

   return $combo.$fincombo;
  } else {

    return $combo.$fincombo;
  }

}
A continuación deberemos crear la función buscarlocalidades que es la que indicamos como función de consulta dentro del Callback:
//Consulta de localidades

function buscarlocalidades()
{

     //Tomo el id de provincia que se envió como parámetro por url al seleccionar
//una provincia del combo idprovincia

  $idprovincia = $this->uri->segment(3);
 

//consulto las localidades segun la provincia seleccionada
  $this->db->select("*")

     ->from('localidades')
     ->where('idprovincia', $idprovincia);

  $db = $this->db->get();
 

        //Asigno la respuesta sql a un array
  $array = array();

  foreach($db->result() as $row):
   $array[] = array("value" => $row->idlocalidad, "property" => $row->localidad);

  endforeach;
 

  echo json_encode($array);
  exit;

}
A continuación deberemos crear la vista que procese los combos y añada las sentencias jquery en forma dinámica para ello crearemos en la carpeta view un archivo denominado combos_dependientes.php.
<?
//Verificamos la operacion o estado de Grocery crud

if(isset($estado) && ($estado == 'add' || $estado == 'edit')) {

//Generamos el script Jquery que controlara los combos dinamicamente
echo '<script type="text/javascript">';

echo '$(document).ready(function() {';
for($i = 0; $i <= sizeof($combos)-1; $i++):

//tomamos las variavles que asignamos en $datos del controlador
echo 'var '.$combos[$i].' = $('select[name="'.$combos[$i].'"]');';

/asignamos el icono
if($i != sizeof($combos)-1) {

  echo '$('#'.$combos[$i].'_input_box').append('<img src="'.$icon_ajax.'" border="0" id="'.$combos[$i].'_ajax_loader" class="dd_ajax_loader" style="display: none;">');';
}


if($i > 0 && $estado == 'add') {

  //Si estamos añadiendo un nuevo registro
        //Ocultamos los combos de jerarquía inferior

  echo '$('#'.$combos[$i].'_input_box').hide();
  echo $combos[$i].'.children().remove().end();';

}
endfor;


for($i = 1; $i <= sizeof($combos)-1; $i++):

/Añadimos los datos a los combos de jerarquia inferior
echo $combos[$i-1].'.change(function() {';

echo 'var select_value = this.value;';
echo '$('#'.$combos[$i-1].'_ajax_loader').show();';

//Borramos todos los datos anteriores
echo $combos[$i].'.find('option').remove();';

echo 'var myOptions = "";';
//Asignamos el nuevo llistado que traemos de buscarlocalidades()

echo '$.getJSON(''.$url[$i].''+select_value, function(data) {';
//listamos los datos

echo $combos[$i].'.append('<option value=""></option>');';
echo '$.each(data, function(key, val) {';

echo $combos[$i].'.append(';
echo '$('<option></option>').val(val.value).html(val.property)';

echo ');';
echo '});';

echo '$('#'.$combos[$i].'_input_box').show();';

for($x = $i+1; $x <= sizeof($combos)-1; $x++):
  echo '$('#'.$combos[$x].'_input_box').hide();';

endfor;

  echo $combos[$i-1].'.each(function(){';
echo '$(this).trigger("liszt:updated");';

echo '});';
echo $combos[$i].'.each(function(){';

echo '$(this).trigger("liszt:updated");';
echo '});';

echo '$('#'.$combos[$i-1].'_ajax_loader').hide();';
echo '});';

echo '});';
endfor;

echo '});';
echo '</script>';

}
?>
Para finalizar vamos a la vista y añadimos el siguiente código que relaciones la vista con el archivo combos_dependientes.php
<?php

if(isset($combo_setup)) {
$this->load->view('combos_dependientes', $combo_setup);

}
?>

grocery6.jpg

 

Luego si ejecutamos podremos ver tanto cuando añadimos un nuevo inmueble o cuando editamos como los combos provincia y localidades han quedado relacionados y localidades, depende de provincia.

 

Si quisiéramos hacer varios combos dependientes deberemos hacer un callback para cada par de combos.

 

Supongamos que tenemos paises, provincias y localidades y queremos hace dependiente países con provincia y provincias con ciudades, entonces deberemos crear un callback para cada dependencias por ejemplo:

$crud->callback_add_field(idprovincia, array($this, 'cbkprovincia'));
$crud->callback_edit_field('idprovincia', array($this, 'cbkprovincia'));


$crud->callback_add_field('idlocalidad', array($this, 'cbklocalidades'));

$crud->callback_edit_field('idlocalidad', array($this, 'cbklocalidades'));
Para el combo países no se crea un callback ya que al ser el primero en jerarquía no tiene dependencia de otro combo.


¿Te ayudó este Tutorial?


15 Comentarios


kalichec123
nov 07 2015 01:07

hola buenas ttardes. gusto en saludarlos. bueno la verdad es que la ultima parte no funciona. hay un error de sintaxis en la parte correspondiente a view en lo de combos_dependientes.php. SI ME HACE ESE INMENSO FAVOR ESTARE ETERNAMENTE AGRADECIDO.. SOLO ME FALTA ARREGLAR ESE ERROR DE SINTAXIS QUE NO LO HE ENCONTRADO POR NINGUN LADO. el resto ya lo tengo corriendo.. agradecimientos si alguien me puede colaborar en esta parte

.


Sergio Culoccioni
nov 08 2015 00:54

hola buenas ttardes. gusto en saludarlos. bueno la verdad es que la ultima parte no funciona. hay un error de sintaxis en la parte correspondiente a view en lo de combos_dependientes.php. SI ME HACE ESE INMENSO FAVOR ESTARE ETERNAMENTE AGRADECIDO.. SOLO ME FALTA ARREGLAR ESE ERROR DE SINTAXIS QUE NO LO HE ENCONTRADO POR NINGUN LADO. el resto ya lo tengo corriendo.. agradecimientos si alguien me puede colaborar en esta parte

.

 

Déjame un mail y te envió los archivos el controlador y la vista funcionando es el mismo código.


kalichec123
nov 10 2015 00:03

listo muchas gracias...


kalichec123
nov 10 2015 00:05

porfa colaboreme con ese codigo de la ultima parte para la vista de combos_dependientes.php


christiandt1
ene 20 2016 19:20

Hola buenas el código lo estoy adaptando a mi proyecto y si creo que el error esta en el archivo combos_dependientes.php ya que la parte de ajax no carga pero si hace todo lo demás.. espero me faciliten los archivos lo agradeceria enormemente


christiandt1
ene 22 2016 18:11

Con los archivos descargados pude resolver muchas gracias. Les dejo lo que me falto seguro les ayudara: en la funcion index() falta colocar el Array algo asi:

//DEPENDENT DROPDOWN SETUP
$datos = array(
//GET THE STATE OF THE CURRENT PAGE - E.G LIST | ADD
'estado' =>  $crud->getState(),
//SETUP YOUR DROPDOWNS
//Parent field item always listed first in array, in this case countryID
//Child field items need to follow in *****, e.g idprovincia then idlocalidad
'combos' => array('idprovincia','idlocalidad'),
//SETUP URL POST FOR EACH CHILD
//List in ***** as per above
'url' => array('', site_url().'/examples/buscarlocalidades/'),
//LOADER THAT GETS DISPLAYED NEXT TO THE PARENT DROPDOWN WHILE THE CHILD LOADS
'icon_ajax' => base_url().'ajax-loader.gif'
);
$output->combo_setup = $datos;
 
Con esto te corre y funciona!!

Jimmy Sierra
abr 19 2016 23:32

Buenas tardes, estoy trabajando con Codeigniter y GroceryCrud y estoy estancado mas de un mes en un problema: "Maestro-Detalle". En el ejemplo que uso usted, seria ver el listado de usuarios y pinchar en uno y mostrara los inmuebles asociados a el. O el ejemplo mas tipico Factura y DetalleFactura. Ya intente con set_relation y set_relation_n_n.

Ojala pueda seguir con su tutorial y tocar este problema.

Saludos

hola,  la ultima parte no funciona. hay un error de sintaxis en la parte correspondiente a view en lo de combos_dependientes.php podrian mandarme los archivos? este es mi correo wian8887@gmail.com

Hola, podrás pasarme los archivos??? no me funciona y no encuentro cual es el problema =(

Te dejo mi correo: verevere@gmail.com

 

Muchas gracias.


Sergio Culoccioni
oct 22 2016 01:52

Hola el código funcionado està publicado para descargar en formato zip al final del tutorial, el archivo es combos.zip


Jesus Ezequiel Montenegro Espinosa
may 07 2017 17:37

hola, ¿aun está ahí el enlace para descargar el archivo combos.zip o fue retirado?,  pues no veo el enlace. Y gracias por el tutorial, me despejó varias dudas que tenia con respecto al Grocery Crud.

Saludos!

Hey muy buen aporte, me podrias ayudar con los archivos fuente a mi correo sirandrewred@gmail.com te agradezco y sigue asi

Hola, alguien tiene los archivos para enviar?


Miguel Angel Lanchazo Perez
dic 23 2020 16:13

Déjame un mail y te envió los archivos el controlador y la vista funcionando es el mismo código.

 

 

Hola el código funcionado està publicado para descargar en formato zip al final del tutorial, el archivo es combos.zip

 

Hola Sergio, No se si por casualidad seguirás manteniendo este código, he seguido los pasos pero me genera errores. Sería posible recibir el código fuente o descargarlo de algún lugar? gracias.


Kevin Alexander Obando Muñoz
jun 27 2021 18:59

Hola PORFAVOR me podriana yudar estoy trabajdno en un proyecto personal de un sistma de registro para inventeario y en la tabla de cliente ncesito hacer este combo independiente entre PROVINCIAS y LOCALIDADES pero no me a funcionado me prodiraa yudar con el codigo funcional GRACIASde anteamo por todo

No esperes más y entra en Solvetic
Deja tus comentarios y aprovecha las ventajas de la cuenta de usuario ¡Únete!

X