Les comparto esta pequeña librería que hice para hacer Selects Dependientes de N niveles con AJAX.
Su uso es bastante simple, solo es instanciar el select y pasar quien es el que depende y el URL para cargar los datos, posteriormente en ese URL van a recibir por GET dos datos, controlName (el nombre del control) y selectedId (el valor que selecciono).
La clase espera recibir un arreglo codificado en JSON, donde cada elemento es un objeto, con una propiedad text, y otra value, de esta forma:
Código:
La forma de uso es bastante simple, basta con tener un HTML:[
{ text: "Texto a mostrar", value: "valor del option" },
{ text: "Texto 2", value: "valor2" },
....
{ text: "Texto n", value: "ValorN" }
]
Código HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="text/javascript" src="prototype.js"></script> <script type="text/javascript" src="dependant.js"></script> <title>Demo Selects Dependientes</title> </head> <body> <select name="sel1" id="sel1"> <option value="">- Selecciona -</option> <option>Mascotas</option> <option>Carros</option> </select> <select name="sel2" id="sel2"><option></option></select> <select name="sel3" id="sel3"><option></option></select> <script type="text/javascript"> Event.observe(window, 'load', function() { var sel3 = new HTMLSelect( 'sel3' ); var sel2 = new dependantSelectAJAX( 'sel2', sel3, 'loader.php' ); var sel1 = new dependantSelectAJAX( 'sel1', sel2, 'loader.php' ); }); </script> </body> </html>
Dejo un pequeño ejemplo de como cargar los datos via PHP, aunque es independiente del lenguaje, el único requisito es que los datos vengan en JSON y con la estructura mencionada mas arriba:
Código PHP:
<?php
$mascotas = array( array( "text" => "Gato", "value" => "cat" ), array( "text" => "Perro", "value" => "dog" ), array( "text" => "Pajaro", "value" => "bird" ) );
$carros = array( array( "text" => "BMW", "value" => "bmw" ), array( "text" => "Lamborghini", "value" => "lamb" ), array( "text" => "Ferrari", "value" => "ferr" ) );
$mascotas_acc_cat = array( array( "text" => "Collar" ), array( "text" => "Estambre" ), array( "text" => "Arena" ) );
$mascotas_acc_dog = array( array( "text" => "Collar" ), array( "text" => "Correa" ), array( "text" => "Pelota" ) );
$mascotas_acc_bird = array( array( "text" => "Jaula" ), array( "text" => "Alpiste" ) );
$carros_color_bmw = array( array( "text" => "Azul" ), array( "text" => "Negro" ) );
$carros_color_lamb = array( array( "text" => "Azul" ), array( "text" => "Amarillo" ), array( "text" => "Rojo" ) );
$carros_color_ferr = array( array( "text" => "Rojo" ) );
switch( $_GET['controlName'] ) {
case 'sel1':
switch( $_GET['selectedId'] ) {
case 'Mascotas':
$result = $mascotas;
break;
case 'Carros':
$result = $carros;
break;
}
break;
case 'sel2':
switch( $_GET['selectedId'] ) {
case 'cat':
$result = $mascotas_acc_cat;
break;
case 'dog':
$result = $mascotas_acc_dog;
break;
case 'bird':
$result = $mascotas_acc_bird;
break;
case 'bmw':
$result = $carros_color_bmw;
break;
case 'lamb':
$result = $carros_color_lamb;
break;
case 'ferr':
$result = $carros_color_ferr;
break;
}
}
echo json_encode( $result );
exit();
?>
Código:
Requiere de la libreria Prototype versión 1.6 minimo debido a la nueva forma de declarar clases.var DataStore = Class.create(Enumerable, {
initialize: function( store ) {
if( store == null ) {
store = [];
}
this._store = store;
},
addItem: function( text, value ) {
if( value == null ) {
value = text;
}
this._store.push( {text: text, value: value } );
},
removeItem: function( idx ) {
this._store.splice( idx, 1 );
},
clear: function() {
this._store = [];
},
size: function() {
return this._store.length;
},
inspect: function() {
alert( this._store.inspect() );
},
_each: function(iterator) {
for (var i = 0; i < this._store.length; i++) {
var value = this._store[i];
iterator(value);
}
}
});
var HTMLSelect = Class.create({
initialize: function( element ) {
this.element = $(element);
this.element.onchange = this.onChange.bindAsEventListener(this);
this.element.onclick = this.onClick.bindAsEventListener(this);
this.element.onfocus = this.onFocus.bindAsEventListener(this);
var store = new DataStore();
var opts = this.element.options;
for(var i = 0; i < opts.length; i++ ) {
var el = opts[i];
store.addItem( el.text, el.value );
}
this.store = store;
},
setStore: function( ds ) {
this.store = ds;
},
reload: function() {
this.empty();
var num = 0;
this.store.each(function(item) {
this.addOption(item.text, item.value);
num++;
}.bind(this));
},
onChange: function(e) {},
onClick: function(e) {},
onFocus: function(e) {},
onEmpty: function() { return true; },
selectIndex: function( index ) {
this.element.selectedIndex = index;
},
selectOption: function( option ) {
var size = this.element.length;
var found = false;
for(i = 0; i < size; i++) {
var el = this.element.options[i].text;
if( el == option ) {
found = true;
break;
}
}
if( found ) {
this.selectIndex(i);
this.onChange();
}
},
countOptions: function() {
return this.element.length;
},
getSelectedOption: function() {
var op = this.element.options[this.element.selectedIndex];
return { value: op.value, text: op.text };
},
getValue: function() {
var op = this.element.options[this.element.selectedIndex];
var ret = "";
ret = op.value;
if( ret == "" ) {
ret = op.text;
}
return ret;
},
empty: function() {
if( this.onEmpty() ) {
this._empty();
}
},
addOption: function( text, value ) {
if( value == null ) {
value = text;
}
var op = new Option( text, value );
var idx = this.element.length;
this.element.options[idx] = op;
return idx;
},
deleteOption: function( index ) {
if( this.element.length > 0 && index > 0 ) {
this.element.options[index] = null;
}
},
selectAllOptions: function() {
var size = this.element.length - 1;
for(i = size; i>=0; i--) {
this.element.options[i].selected = true;
}
},
getSelectedOptions: function() {
var texts = [];
var size = this.element.length - 1;
for(i = size; i>=0; i--) {
if( this.element.options[i].selected === true ) {
texts.push(this.element.options[i].text);
}
}
return texts;
},
_empty: function() {
this.element.options.length = 0;
}
});
var dependantSelectAJAX = Class.create(HTMLSelect, {
initialize: function( $super, select, child, url ) {
$super( select );
if( typeof( select ) == "string" ) {
this.name = select;
} else {
this.name = select.name;
}
this.child = child;
this.url = url;
},
onChange: function(e) {
this.child.empty();
var value = this.getValue();
if( value != "" ) {
var request = new Ajax.Request( this.url, {
method: 'get',
parameters: {controlName: this.name, selectedId: value},
onSuccess: function( transport ) {
var store = transport.responseText.evalJSON(true);
if( typeof store.error != "undefined" ) {
alert( store.error );
} else {
this.child.setStore(new DataStore(store));
this.child.reload();
var size = this.child.countOptions();
if( size == 1 ) {
this.child.onChange();
}
}
}.bind(this),
onFalure: function(t) {
alert( "Error in request" );
}
});
}
},
onEmpty: function() {
this.child.empty();
return true;
}
});
Saludos y espero les sea de utilidad.

, pero de cualquier forma, sirve correctamente.

Este tema le ha gustado a 2 personas