Forma HTML de solo lectura SELECCIONE etiqueta / entrada

589

Según las especificaciones HTML, la selectetiqueta en HTML no tiene un readonlyatributo, solo un disabledatributo. Entonces, si desea evitar que el usuario cambie el menú desplegable, debe usarlo disabled.

El único problema es que las entradas de formulario HTML deshabilitadas no se incluyen en los datos POST / GET.

¿Cuál es la mejor manera de emular el readonlyatributo de una selectetiqueta y aún así obtener los datos POST?

Jrgns
fuente
55
No confíe en eso para el lado del servidor. Cualquiera puede crear su propia página HTML y convertirla en RW.
Brendan Byrd
11
Pero no es una pregunta específica de PHP.
Kaleb Brasee
44
Sugeriría no usar un elemento select en absoluto en este caso. ¿Hay alguna razón por la que no pueda mostrar el valor como texto sin formato?
Big McLargeHuge
2
@ppumkin tu comentario no tiene sentido. No digo que nunca haya un buen caso de uso para campos de formulario seleccionados u ocultos. El OP estaba teniendo problemas para mostrar texto en la página, y simplemente me preguntaba cuál era el propósito de usar un elemento select en este caso.
Big McLargeHuge
2
Debo estar leyendo la pregunta equivocada. Él dice que quiere deshabilitar la selección para que el usuario no la cambie. Tal vez necesita renderizar la página con selecciones y usar jquery para evitar cambios. Pero cuando lo envía de nuevo, no hay datos para ello. Estaba haciendo lo mismo Necesito mostrar selecciones filtradas por otras selecciones y el último menú desplegable se guarda en DB a través de ajax, por lo que todo lo anterior debe bloquearse. Cuando renderizo la página, sí, OK, podría mostrar etiquetas en lugar de selecciones. Pero ese no es el problema :)
Piotr Kula

Respuestas:

461

Debe mantener el selectelemento disabledpero también agregar otro oculto inputcon el mismo nombre y valor.

Si vuelve a habilitar su SELECT, debe copiar su valor a la entrada oculta en un evento onchange y deshabilitar (o eliminar) la entrada oculta.

Aquí hay una demostración:

$('#mainform').submit(function() {
    $('#formdata_container').show();
    $('#formdata').html($(this).serialize());
    return false;
});

$('#enableselect').click(function() {
    $('#mainform input[name=animal]')
        .attr("disabled", true);
    
    $('#animal-select')
        .attr('disabled', false)
    	.attr('name', 'animal');
    
    $('#enableselect').hide();
    return false;
});
#formdata_container {
    padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
    <form id="mainform">
        <select id="animal-select" disabled="true">
            <option value="cat" selected>Cat</option>
            <option value="dog">Dog</option>
            <option value="hamster">Hamster</option>
        </select>
        <input type="hidden" name="animal" value="cat"/>
        <button id="enableselect">Enable</button>
        
        <select name="color">
            <option value="blue" selected>Blue</option>
            <option value="green">Green</option>
            <option value="red">Red</option>
        </select>

        <input type="submit"/>
    </form>
</div>

<div id="formdata_container" style="display:none">
    <div>Submitted data:</div>
    <div id="formdata">
    </div>
</div>

bezmax
fuente
55
Si vuelve a habilitar la selección, también debe desactivar o eliminar la entrada oculta (después de copiar su valor como se describe), por supuesto. De lo contrario, obtendrá el valor presentado doble
Adam
1
@max Ah !. Ok, eso también funciona. Asumí desde que dijo que la entrada oculta debería tener el "mismo nombre" que la selección tenía un nombre.
Adam
2
¿Qué pasa si estoy usando una selección múltiple?
Anyul Rivas
2
Tener dos elementos con los mismos nombres solo devolverá la última entrada habilitada / seleccionada, no el doble. Además, solo selectedse devuelve el valor, no toda la lista. Entonces, tu se hiddensienta antes que tu selecty tiene el valor seleccionado. Si la selección se deshabilita para "solo lectura", la publicación posterior solo contendrá el valor de la entrada oculta. Si la selección está habilitada, la opción seleccionada visible "sobrescribirá / reemplazará" el valor oculto, y ese es el valor que se volverá a publicar.
Piotr Kula
30
Si bien esta es la solución obvia, es una solución, ya que debe agregar otro campo de entrada.
Donato
190

También podríamos usar esto

Deshabilitar todo excepto la opción seleccionada:

<select>
    <option disabled>1</option>
    <option selected>2</option>
    <option disabled>3</option>
</select>

De esta manera, el menú desplegable aún funciona (y envía su valor) pero el usuario no puede seleccionar otro valor.

Manifestación

vimal1083
fuente
3
Bonito para opciones dinámicas
Diego Favero
11
¡Perfecto para una etiqueta SELECT de valor único! Pero no funcionará para un <select multiple>, que aún permitirá a los usuarios anular la selección de algunas de las opciones seleccionadas, cambiando así el valor.
Mikhail Bunkin
2
Soporte del navegador para el atributo de la optionetiquetadisabled
Jo.
44
Esta es una gran solución. Agregaré que puedes lograrlo fácilmente con jQuery así: $("#yourSelectId option:not(:selected)).attr("disabled", "disabled")
Onkel-j
105

Puede volver a habilitar el objeto seleccionado al enviar.

EDITAR : es decir, normalmente deshabilita la etiqueta de selección (con el atributo deshabilitado) y luego la vuelve a habilitar automáticamente justo antes de enviar el formulario:

Ejemplo con jQuery:

  • Para deshabilitarlo:

    $('#yourSelect').prop('disabled', true);
  • Para volver a habilitarlo antes del envío para que se incluyan los datos GET / POST:

    $('#yourForm').on('submit', function() {
        $('#yourSelect').prop('disabled', false);
    });

Además, puede volver a habilitar cada entrada deshabilitada o seleccionar:

$('#yourForm').on('submit', function() {
    $('input, select').prop('disabled', false);
});
kemiller2002
fuente
44
use .prop ('disabled', verdadero / falso) para establecer la propiedad deshabilitada. El atributo no cambiará el estado real.
Paris Char
Creo que esta solución es más inteligente que la solución @bezmax . Porque si agregamos entradas ocultas, tenemos que considerar que solo una de cada entradas (mismo nombre) estaba habilitada en cualquier momento. De lo contrario, si ambas entradas estaban habilitadas, en el lado del servidor, el programa tomará una matriz de entrada que puede causar una excepción (por ejemplo, si no manejamos esta situación, y esperamos una cadena y use 'Request.Form [FieldName] 'comando)
MiT
@Kevin, funciona> 90% de casos. Además, tienes que tener jquery en tu cinturón ... Eh.
sitilge
Esto es mucho más limpio la respuesta aceptada. Es más fácil deshacer la lógica si ya no desea deshabilitar el elemento y no hay etiquetas de entrada adicionales.
Haohmaru
51

Otra forma de hacer un readOnlyatributo a un selectelemento es mediante el uso decss

podrías hacer como:

$('#selection').css('pointer-events','none');

MANIFESTACIÓN

Yaje
fuente
8
Buena solución Pero aún puede cambiar el valor con el teclado.
Mario Werner
1
Sí, esto es bastante impresionante. Para cambiar el valor con el teclado, tendría que pulsar TAB en el elemento y luego se seleccionará. Si hace que el color de fondo sea gris o deshabilitado, también está informando visualmente al usuario que está "deshabilitado" cuando en realidad no está deshabilitado. Ya nadie es compatible con IE, a quién le importa. También puede poner un keydown prevent default por defecto si quiere evitarlo.
Piotr Kula
¡Muy poco ortodoxo! Si la selección necesita ser bloqueada desde el renderizado de la página,... .on('mouseover', function(){ ... });
Fr0zenFyr
pointer-events: noneevita el foco del cursor del mouse. Para evitar también el enfoque del teclado, puede complementarlo difuminando inmediatamente todos los eventos de enfoque:$('select').css('pointer-events', 'none').on('focus', function () {$(this).blur();});
Quinn Comendant
39
<select id="countries" onfocus="this.defaultIndex=this.selectedIndex;" onchange="this.selectedIndex=this.defaultIndex;">
<option value="1">Country1</option>
<option value="2">Country2</option>
<option value="3">Country3</option>
<option value="4">Country4</option>
<option value="5">Country5</option>
<option value="6">Country6</option>
<option value="7" selected="selected">Country7</option>
<option value="8">Country8</option>
<option value="9">Country9</option>
</select>

Probado y funcionando en IE 6, 7 y 8b2, Firefox 2 y 3, Opera 9.62, Safari 3.2.1 para Windows y Google Chrome.

Grant Wagner
fuente
15
El problema con esto es que el menú desplegable se representa como si no fuera de solo lectura. El usuario pensará que la cosa no funciona ...
Lukas Eder
8
Esto es confuso para el usuario porque aún puede seleccionar una opción, pero cuando la seleccionan, la lista vuelve al valor seleccionado previamente. Es mucho más intuitivo deshabilitar la lista para evitar que el usuario seleccione cualquier cosa.
dana
11
Tuve un problema similar y lo resolví solo mostrando la opción seleccionada. No se requiere JS, menos confusión para el usuario ... <select id="countries"> <option value="7" selected="selected">Country7</option> </select>
Potherca 05 de
1
@ppumkin @dana @LukasEder No ... no si puedes arreglar este UX. Por ejemplo, podría hacer algo como en onchange = 'this.selectedIndex=this.defaultIndex; alert("You should not change this..");'lugar de simplemente cambiar el índice seleccionado en silencio ...
Fr0zenFyr
1
@LukasEder Para cualquier persona recelosa sobre la experiencia del encuestado, pueden agregar algo de CSS para enfatizar realmente que el menú desplegable no debe cambiarse. Ajuste el cursor a not-allowedy el color de fondo a #CCC.
Alexander Dixon
36

Solución jQuery simple

Use esto si sus selecciones tienen la readonlyclase

jQuery('select.readonly option:not(:selected)').attr('disabled',true);

O esto si sus selecciones tienen el readonly="readonly"atributo

$('select[readonly="readonly"] option:not(:selected)').attr('disabled',true);
Software de ladrillo negro
fuente
77
Por favor, explique un poco su código. ¿Tenemos que agregar una clase 'solo lectura' a los elementos seleccionados? ¿Cuándo tenemos que llamar a este código: solo en document.ready o cada vez que una selección está habilitada / deshabilitada? ¿Es seguro su código noscript?
anar khalilov
$(document).ready(function(){$('select option:not(:selected)').attr('disabled',true);});funciona bien en selección única. No se requiere una clase de "solo lectura". La selección múltiple es problemática porque si hay más de una opción ya seleccionada y, por lo tanto, no está deshabilitada y un usuario selecciona una de las opciones no deshabilitadas, las otras opciones previamente seleccionadas no se seleccionan.
Gordon
No entiendo nada de esto.
Piotr Kula
Deshabilita las opciones que no sean las seleccionadas para cuadros de selección con clase "solo lectura". Si tiene el elemento select en la mano, puede escribir:$select.find('option').not(':selected').attr('disabled', 'disabled');
Semra
1
Me gusta esta solución Cambiaría el selector a select[readonly]para que solo agregue el atributo de solo lectura al elemento, de esta manera no tendrá que tratar las selecciones de manera diferente a cualquier otro tipo. El javascript luego mejora progresivamente el efecto. Tenga en cuenta que esta solución (y la mayoría de las otras) solo ayuda al agente de usuario a proporcionar la mejor experiencia de usuario; en realidad no aplica nada (que debe hacerse del lado del servidor si es necesario).
jgivoni
21

Solución CSS simple:

select[readonly]{
    background: #eee;
    cursor:no-drop;
}

select[readonly] option{
    display:none;
}

Esto da como resultado Seleccionar para ser gris con un bonito cursor "deshabilitar" al pasar el mouse
y al seleccionar la lista de opciones está "vacía", por lo que no puede cambiar su valor.

d.raev
fuente
1
Si tiene una validación CSRF (como en Symfony y muchos otros marcos), no funcionará.
ThEBiShOp
11

Esta es la mejor solución que he encontrado:

$("#YourSELECTIdHere option:not(:selected)").prop("disabled", true);

El código anterior deshabilita todas las demás opciones no seleccionadas mientras mantiene habilitada la opción seleccionada. Al hacerlo, la opción seleccionada pasará a los datos posteriores.

Leniel Maccaferri
fuente
11

Sé que es demasiado tarde, pero se puede hacer con CSS simple:

select[readonly] option, select[readonly] optgroup {
    display: none;
}

El estilo oculta todas las opciones y los grupos cuando la selección está en readonly estado, por lo que el usuario no puede cambiar su selección.

No se necesitan hacks de JavaScript.

nrofis
fuente
Agradable y simple Me gusta.
Jonathan Parent Lévesque
Esta es una muy buena solución al problema. ¡Gracias!
OderWat
10

Aún más fácil: agregue el atributo de estilo a su etiqueta seleccionada :

style="pointer-events: none;"
mainak chakraborty
fuente
¿Funciona para mí, pero los eventos de puntero harán que los navegadores cruzados sean compatibles?
Abhijit Jagtap
3
No funcionará El usuario puede cambiar la entrada usando el teclado.
Sandhu
6

Esta es la mejor y más simple solución. Establecerá un atributo readolny en su selección, o cualquier otro atributo como solo lectura de datos, y hará lo siguiente

$("select[readonly]").live("focus mousedown mouseup click",function(e){
    e.preventDefault();
    e.stopPropagation();
});
Guilherme Ferreira
fuente
1
debe agregar keyup ad keydown aquí, así como el menú desplegable todavía está disponible "tabulándolo" y usar las teclas de flecha para cambiar el valor.
apfz
5

Establezca la opción deshabilitada cuando planee que sea de solo lectura y luego elimine el atributo deshabilitado justo antes de enviar el formulario.

// global variable to store original event/handler for save button
var form_save_button_func = null;

// function to get jQuery object for save button
function get_form_button_by_id(button_id) {
    return jQuery("input[type=button]#"+button_id);
}

// alter value of disabled element
function set_disabled_elem_value(elem_id, value)  {
    jQuery("#"+elem_id).removeAttr("disabled");
    jQuery("#"+elem_id).val(value);
    jQuery("#"+elem_id).attr('disabled','disabled');
}

function set_form_bottom_button_save_custom_code_generic(msg) {
    // save original event/handler that was either declared
    // through javascript or html onclick attribute
    // in a global variable
    form_save_button_func = get_form_button_by_id('BtnSave').prop('onclick'); // jQuery 1.6
    //form_save_button_func = get_form_button_by_id('BtnSave').prop('onclick'); // jQuery 1.7

    // unbind original event/handler (can use any of following statements below)
    get_form_button_by_value('BtnSave').unbind('click');
    get_form_button_by_value('BtnSave').removeAttr('onclick');

    // alternate save code which also calls original event/handler stored in global variable
    get_form_button_by_value('BtnSave').click(function(event){
        event.preventDefault();
        var confirm_result = confirm(msg);
        if (confirm_result) {
            if (jQuery("form.anyForm").find('input[type=text], textarea, select').filter(".disabled-form-elem").length > 0) {
                jQuery("form.anyForm").find('input[type=text], textarea, select').filter(".disabled-form-elem").removeAttr("disabled");
            }

            // disallow further editing of fields once save operation is underway
            // by making them readonly
            // you can also disallow form editing by showing a large transparent
            // div over form such as loading animation with "Saving" message text
            jQuery("form.anyForm").find('input[type=text], textarea, select').attr('ReadOnly','True');

            // now execute original event/handler
            form_save_button_func();
        }
    });
}

$(document).ready(function() {
    // if you want to define save button code in javascript then define it now

    // code below for record update
    set_form_bottom_button_save_custom_code_generic("Do you really want to update this record?");
    // code below for new record
    //set_form_bottom_button_save_custom_code_generic("Do you really want to create this new record?");

    // start disabling elements on form load by also adding a class to identify disabled elements
    jQuery("input[type=text]#phone").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("input[type=text]#fax").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("select#country").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("textarea#address").addClass('disabled-form-elem').attr('disabled','disabled');

    set_disabled_elem_value('phone', '123121231');
    set_disabled_elem_value('fax', '123123123');
    set_disabled_elem_value('country', 'Pakistan');
    set_disabled_elem_value('address', 'address');

}); // end of $(document).ready function
Craig Ambrose
fuente
Eso suena como una condición de carrera esperando a suceder.
Brendan Byrd
5

Además de deshabilitar las opciones que no deberían ser seleccionables, quería hacerlas desaparecer de la lista, pero aún así poder habilitarlas si necesito hacerlo más tarde:

$("select[readonly]").find("option:not(:selected)").hide().attr("disabled",true);

Esto busca todos los elementos de selección con un atributo de solo lectura, luego encuentra todas las opciones dentro de las selecciones que no están seleccionadas, luego las oculta y las desactiva.

Es importante separar la consulta jquery en 2 por razones de rendimiento, porque jquery las lee de derecha a izquierda, el código:

$("select[readonly] option:not(:selected)")

primero encontrará todas las opciones no seleccionadas en el documento y luego filtrará las que están dentro de las selecciones con un atributo de solo lectura.

cernunnos
fuente
Quizás en su .prop("disabled", true)lugar
sam
4

Un enfoque simple del lado del servidor es eliminar todas las opciones excepto la que desea que se seleccione. Por lo tanto, en Zend Framework 1.12, si $ element es un Zend_Form_Element_Select:

 $value =  $element->getValue();
 $options = $element->getAttrib('options');
 $sole_option = array($value => $options[$value]);
 $element->setAttrib('options', $sole_option);
David
fuente
4

Si deshabilita un campo de formulario, este no se enviará cuando se envíe el formulario. Entonces, si necesitas un readonlyque funcione comodisabled pero enviando valores, haga esto:

Después de cualquier cambio en las propiedades de solo lectura de un elemento.

$('select.readonly option:not(:selected)').attr('disabled',true);

$('select:not([readonly]) option').removeAttr('disabled');
Joaquim Perez
fuente
4

Solución con tabindex. Funciona con select pero también con entradas de texto.

Simplemente use una clase .disabled.

CSS:

.disabled {
    pointer-events:none; /* No cursor */
    background-color: #eee; /* Gray background */
}

JS:

$(".disabled").attr("tabindex", "-1");

HTML:

<select class="disabled">
    <option value="0">0</option>
</select>

<input type="text" class="disabled" />

Editar: con Internet Explorer, también necesita este JS:

$(document).on("mousedown", ".disabled", function (e) {
    e.preventDefault();
});
jBelanger
fuente
2

Siguiendo con la sugerencia de Grant Wagners; Aquí hay un fragmento de jQuery que lo hace con funciones de controlador en lugar de atributos directos onXXX:

var readonlySelect = function(selector, makeReadonly) {

    $(selector).filter("select").each(function(i){
        var select = $(this);

        //remove any existing readonly handler
        if(this.readonlyFn) select.unbind("change", this.readonlyFn);
        if(this.readonlyIndex) this.readonlyIndex = null;

        if(makeReadonly) {
            this.readonlyIndex = this.selectedIndex;
            this.readonlyFn = function(){
                this.selectedIndex = this.readonlyIndex;
            };
            select.bind("change", this.readonlyFn);
        }
    });

};
thetoolman
fuente
2

Lo resolví con jquery:

      $("select.myselect").bind("focus", function(){
        if($(this).hasClass('readonly'))
        {
          $(this).blur();   
          return;
        }
      });
ser dueño
fuente
Esto funcionó muy bien, aunque la animación del mouseover todavía mostrará una flecha desplegable que parece cliqueable.
Johncl
Esto no me funciona en Chrome 26: la selección sigue siendo completamente funcional.
Andy
Pero aún aparece la lista cuando hace doble clic en IE. De todos modos para evitar eso?
user1995781
2

Si está utilizando jquery validate, puede hacer lo siguiente a continuación, utilicé el atributo deshabilitado sin ningún problema:

$(function(){
    $('#myform').validate({
        submitHandler:function(form){
            $('select').removeAttr('disabled');
            form.submit();
        }
    });
});
Rafael Moni
fuente
2

Lo que encontré funciona muy bien, con javascript simple (es decir: no se requiere la biblioteca JQuery), es cambiar el innerHTML de la <select>etiqueta al valor restante único deseado.

Antes de:

<select name='day' id='day'>
  <option>SUN</option>
  <option>MON</option>
  <option>TUE</option>
  <option>WED</option>
  <option>THU</option>
  <option>FRI</option>
  <option>SAT</option>
</select>

Javascript de muestra:

document.getElementById('day').innerHTML = '<option>FRI</option>';

Después:

<select name='day' id='day'>
  <option>FRI</option>
</select>

De esta manera, no cambiará el efecto visual, y esto POST / GET dentro de <FORM>.

Syd
fuente
1

En lugar de seleccionar en sí, puede deshabilitar todas las opciones, excepto la opción seleccionada actualmente. Esto da la apariencia de un menú desplegable de trabajo, pero solo la opción que desea pasar es una selección válida.

Adam Bellaire
fuente
3
En teoría, es una gran idea, pero NO hay soporte para opciones deshabilitadas en IE antes de IE8. tinyurl.com/yle4bto
scunliffe
1

solución html:

<select onfocus="this.blur();">

los de javascript:

selectElement.addEventListener("focus", selectElement.blur, true); selectElement.attachEvent("focus", selectElement.blur); //thanks, IE

para eliminar:

selectElement.removeEventListener("focus", selectElement.blur, true); selectElement.detachEvent("focus", selectElement.blur); //thanks, IE

editar: se agregaron métodos de eliminación

Kadmillos
fuente
@ButtleButkus ¿funcionan los javascript? supongo que puede ser un navegador relacionado issue.have ha intentado agregar un índice de tabulación al elemento
Kadmillos
1

Simplemente, elimine el atributo deshabilitado antes de enviar el formulario.

    $('form').submit(function () {
        $("#Id_Unidade").attr("disabled", false);
    });
Wendell Carvalho
fuente
1
<select id="case_reason" name="case_reason" disabled="disabled">

disabled="disabled" ->obtendrá su valor de la base de datos y lo mostrará en el formulario. readonly="readonly" ->puede cambiar su valor en selectbox, pero su valor no se pudo guardar en su base de datos.

Afwan Zikri
fuente
mal, está guardado. Parece que la propiedad 'readonly' no es procesada por todos los navegadores y, por lo tanto, no es confiable.
Richey
0

Si el menú desplegable de selección es de solo lectura desde el nacimiento y no necesita cambiar en absoluto, ¿tal vez debería usar otro control? Como un simple <div>(más un campo de formulario oculto) o un<input type="text"> ?

Agregado: si el menú desplegable no es de solo lectura todo el tiempo y se usa JavaScript para habilitarlo / deshabilitarlo, entonces esta sigue siendo una solución: simplemente modifique el DOM sobre la marcha.

Vilx-
fuente
No es de solo lectura desde el principio. Yo uso JavaScript para cambiar y actualizar. Si un menú desplegable anterior tiene un cierto valor, este se convierte en de solo lectura.
Jrgns
Entonces, ¿tal vez pueda reemplazar este menú desplegable con un cuadro de texto sobre la marcha?
Vilx-
Sí, pero la entrada siempre oculta es más elegante en mi opinión
Jrgns
0

A continuación funcionó para mí:

$('select[name=country]').attr("disabled", "disabled"); 
Juan
fuente
11
FYI: el campo de formulario deshabilitado no se incluirá en un envío.
mz_01
0

Lo logré ocultando el cuadro de selección y mostrando un spanen su lugar con solo valor informativo. En el caso de deshabilitar la .readonlyclase, también necesitamos eliminar los .toVanishelementos y mostrar los elementos .toShow.

 $( '.readonly' ).live( 'focus', function(e) {
                $( this ).attr( 'readonly', 'readonly' )
                if( $( this ).get(0).tagName == 'SELECT' ) {
                    $( this ).before( '<span class="toVanish readonly" style="border:1px solid; padding:5px">' 
                            + $( this ).find( 'option:selected' ).html() + '</span>' )
                    $( this ).addClass( 'toShow' )
                    $( this ).hide()
            }
    });
fiatjaf
fuente
0

En IE pude derrotar el enfoque onfocus => onblur haciendo doble clic. Pero recordar el valor y luego restaurarlo en el evento onchange parece manejar ese problema.

<select onfocus="this.oldvalue=this.value;this.blur();" onchange="this.value=this.oldvalue;">
....
</select>

Puede hacer algo similar sin expandir las propiedades utilizando una variable javascript.

Sojourneer
fuente
0

Aquí hay un intento de usar una función jQuery personalizada para lograr la funcionalidad (como se menciona aquí):

$(function(){

 $.prototype.toggleDisable = function(flag) {
    // prepare some values
    var selectId = $(this).attr('id');
    var hiddenId = selectId + 'hidden';
    if (flag) {
      // disable the select - however this will not submit the value of the select
      // a new hidden form element will be created below to compensate for the 
      // non-submitted select value 
      $(this).attr('disabled', true);

      // gather attributes
      var selectVal = $(this).val();
      var selectName = $(this).attr('name');

      // creates a hidden form element to submit the value of the disabled select
      $(this).parents('form').append($('<input></input>').
        attr('type', 'hidden').
        attr('id', hiddenId).
        attr('name', selectName).
        val(selectVal) );
    } else {
      // remove the newly-created hidden form element
      $(this).parents('form').remove(hiddenId);
      // enable back the element
      $(this).removeAttr('disabled');
    }
  }

  // Usage
  // $('#some_select_element').toggleDisable(true);
  // $('#some_select_element').toggleDisable(false);

});
tamersalama
fuente