¿Cómo asegurar que se envíe un campo de formulario <select> cuando está deshabilitado?

180

Tengo un selectcampo de formulario que quiero marcar como "solo lectura", ya que el usuario no puede modificar el valor, pero el valor aún se envía con el formulario. El uso del disabledatributo evita que el usuario cambie el valor, pero no envía el valor con el formulario.

El readonlyatributo solo está disponible para inputy textareacampos, pero eso es básicamente lo que quiero. ¿Hay alguna manera de hacer que eso funcione?

Dos posibilidades que estoy considerando incluyen:

  • En lugar de deshabilitar select, deshabilite todos los mensajes de correo electrónico optiony use CSS para atenuar la selección para que parezca deshabilitada.
  • Agregue un controlador de eventos de clic al botón de envío para que habilite todos los menús desplegables deshabilitados antes de enviar el formulario.
Marqués Wang
fuente
2
perdón por unirse tarde, sin embargo, las soluciones proporcionadas por @ trafalmadorianworkest son las mejores. Deshabilita todas las entradas que no están seleccionadas. También funcionaría si selecciona tiene múltiples opciones habilitadas. $('#toSelect')find(':not(:selected)').prop('disabled',true);
Abhishek Madhani
Alternativamente, puede dejar el control como deshabilitado en la IU pero recuperar el valor en el método de acción: public ActionResult InsertRecord (MyType model) {if (model.MyProperty == null) {model.MyProperty = Request ["MyProperty"]; }}
beastieboy

Respuestas:

118
<select disabled="disabled">
    ....
</select>
<input type="hidden" name="select_name" value="selected value" />

¿Dónde select_nameestá el nombre que normalmente le daría al<select> .

Otra opción.

<select name="myselect" disabled="disabled">
    <option value="myselectedvalue" selected="selected">My Value</option>
    ....
</select>
<input type="hidden" name="myselect" value="myselectedvalue" />

Ahora con este, he notado que dependiendo del servidor web que esté utilizando, es posible que tenga que poner la hiddenentrada antes o después del<select> .

Si mi memoria me sirve correctamente, con IIS, lo pones antes, con Apache lo pones después. Como siempre, la prueba es clave.

Jordan S. Jones
fuente
3
¿Cómo dependería esto del servidor web ? ¿No es el cliente el que presenta la página con el campo de selección y, por lo tanto, en caso de conflicto, sería el cliente el que decida si enviar el valor al servidor o no?
Ilari Kajaste
8
Depende de cómo el servidor maneja múltiples entradas con el mismo nombre.
Jordan S. Jones
1
Será mejor que no confíes en un tipo de servidor específico, por lo que creo que el primer enfoque es más limpio y menos propenso a errores ...
Luke
55
@ Jordan: los navegadores no envían valores de campos deshabilitados al servidor, por lo que están vacíos cuando intenta manejarlos en el lado del servidor. Si tiene un campo oculto con el valor deseado y los campos visibles están deshabilitados, solo el campo oculto se enviará al servidor. Ergo, el campo oculto solo debe crearse (a través de JS o código del lado del servidor) cuando los campos visibles están deshabilitados y no hay un problema de prioridad.
Matt van Andel
1
Esta es la única opción si necesita un formulario que funcione sin javascript.
Andrew
224

Deshabilite los campos y luego habilítelos antes de enviar el formulario:

Código jQuery:

jQuery(function ($) {        
  $('form').bind('submit', function () {
    $(this).find(':input').prop('disabled', false);
  });
});
Tres
fuente
15
¡Qué buena solución!
Chris
2
Este es el que me decidí, principalmente porque es el menos molesto.
Jonathan
3
Los documentos de jQuery recomiendan usar .prop y .removeProp para 'marcado', 'seleccionado' y 'deshabilitado' en lugar de .attr y .removeAttr, consulte http://api.jquery.com/prop/
Jim Bergman
2
Pedazo relevante del comentario de @ JimBergman: "Las propiedades generalmente afectan el estado dinámico de un elemento DOM sin cambiar el atributo HTML serializado. Los ejemplos incluyen la propiedad de valor de los elementos de entrada, la propiedad deshabilitada de entradas y botones, o la propiedad marcada de una casilla de verificación. El método .prop () debe usarse para establecer deshabilitado y marcado en lugar del método .attr (). El método .val () debe usarse para obtener y establecer el valor ". - de api.jquery.com/prop
Joshua Dance
2
Eres un genio (Y)
TommyDo
13

He estado buscando una solución para esto, y como no encontré una solución en este hilo, hice la mía.

// With jQuery
$('#selectbox').focus(function(e) {
    $(this).blur();
});

Simple, simplemente desenfoca el campo cuando te enfocas en él, algo así como deshabilitarlo, pero en realidad envías sus datos.

Jean Paul Rumeau
fuente
Wow Gran y fácil solución. Gracias .. +1 de mi parte :)
Naeem Ul Wahhab
Esto me gusta mucho ... dependiendo de las interacciones en mi forma, los elementos se habilitan / deshabilitan de un lado a otro ... ¿cómo puedo volver a habilitar un campo 'borroso' en este escenario?
bkwdesign
Desde googlear, se ve como $ ('# selectbox'). Off ('focus'); haría el truco de volver a habilitar
bkwdesign
2
funciona para cuadros de texto, no funciona para cuadros seleccionados, además de súper fácil moverse haciendo clic y manteniendo presionado el botón
Andrew
7

Me enfrenté a un escenario ligeramente diferente, ya que solo quería no permitir que el usuario cambiara el valor seleccionado en función de un cuadro de selección anterior. Lo que terminé haciendo fue deshabilitar todas las otras opciones no seleccionadas en el cuadro de selección usando

$('#toSelect')find(':not(:selected)').attr('disabled','disabled');
trafalmadorian
fuente
Gracias, encontré el tuyo lógicamente más simple. Sin embargo, attrdebería cambiar con prop, se vería algo así$('#toSelect')find(':not(:selected)').prop('disabled',true);
Abhishek Madhani
6

La misma solución sugerida por Tres sin usar jQuery

<form onsubmit="document.getElementById('mysel').disabled = false;" action="..." method="GET">

   <select id="mysel" disabled="disabled">....</select>

   <input name="submit" id="submit" type="submit" value="SEND FORM">
</form>

Esto podría ayudar a alguien a entender más, pero obviamente es menos flexible que el de jQuery.

Marco Demaio
fuente
Pero, no es bueno para múltiples selectores. Puede ser que podamos usar getElementsByTagName('select')?
Afortunado el
6

no funciona con el: selector de entrada para campos seleccionados, use esto:

    jQuery(function() {

    jQuery('form').bind('submit', function() {
        jQuery(this).find(':disabled').removeAttr('disabled');
    });

    });
chhalpha
fuente
5

Uso el siguiente código para deshabilitar las opciones en las selecciones

<select class="sel big" id="form_code" name="code" readonly="readonly">
   <option value="user_played_game" selected="true">1 Game</option>
   <option value="coins" disabled="">2 Object</option>
   <option value="event" disabled="">3 Object</option>
   <option value="level" disabled="">4 Object</option>
   <option value="game" disabled="">5 Object</option>
</select>

// Disable selection for options
$('select option:not(:selected)').each(function(){
 $(this).attr('disabled', 'disabled');
});
Aleks
fuente
4

La forma más fácil que encontré fue crear una pequeña función de JavaScript vinculada a su formulario:

function enablePath() {
    document.getElementById('select_name').disabled= "";
}

y lo llamas en tu formulario aquí:

<form action="act.php" method="POST" name="form_name" onSubmit="enablePath();">

O puede llamarlo en la función que utiliza para verificar su formulario :)

Alex PARISOT
fuente
4

Simplemente agregue una línea antes de enviar.

$ ("# XYZ"). RemoveAttr ("disabled");

PPB
fuente
2

O use JavaScript para cambiar el nombre de la selección y configurarla como deshabilitada. De esta manera, la selección aún se envía, pero con un nombre que no está marcando.

Byron Whitlock
fuente
2

Creé un complemento rápido (solo Jquery), que guarda el valor en un campo de datos mientras una entrada está deshabilitada. Esto solo significa que mientras el campo se deshabilite programáticamente mediante jquery usando .prop () o .attr () ... luego acceder al valor mediante .val (), .serialize () o .serializeArra () siempre devolverá el valor incluso si está deshabilitado :)

Enchufe descarado: https://github.com/Jezternz/jq-disabled-inputs

Josh Mc
fuente
2

Basado en la solución de Jordan, creé una función que crea automáticamente una entrada oculta con el mismo nombre y el mismo valor de la selección que desea invalidar. El primer parámetro puede ser un id o un elemento jquery; el segundo es un parámetro opcional booleano donde "verdadero" deshabilita y "falso" habilita la entrada. Si se omite, el segundo parámetro cambia la selección entre "habilitado" y "deshabilitado".

function changeSelectUserManipulation(obj, disable){
    var $obj = ( typeof obj === 'string' )? $('#'+obj) : obj;
    disable = disable? !!disable : !$obj.is(':disabled');

    if(disable){
        $obj.prop('disabled', true)
            .after("<input type='hidden' id='select_user_manipulation_hidden_"+$obj.attr('id')+"' name='"+$obj.attr('name')+"' value='"+$obj.val()+"'>");
    }else{
        $obj.prop('disabled', false)
            .next("#select_user_manipulation_hidden_"+$obj.attr('id')).remove();
    }
}

changeSelectUserManipulation("select_id");
Doglas
fuente
el parámetro 'obj' debe ser un objeto jquery
Doglas
1

Encontré una solución viable: eliminar todos los elementos excepto el seleccionado. Luego puede cambiar el estilo a algo que también parezca deshabilitado. Usando jQuery:

jQuery(function($) {
    $('form').submit(function(){
        $('select option:not(:selected)', this).remove();
    });
});
Alftheo
fuente
0
<select id="example">
    <option value="">please select</option>
    <option value="0" >one</option>
    <option value="1">two</option>
</select>



if (condition){
    //you can't select
    $("#example").find("option").css("display","none");
}else{
   //you can select
   $("#example").find("option").css("display","block");
}
Thxopen
fuente
-8

Otra opción es utilizar el atributo de solo lectura.

<select readonly="readonly">
    ....
</select>

Con solo lectura, el valor aún se envía, el campo de entrada aparece atenuado y el usuario no puede editarlo.

Editar:

Citado de http://www.w3.org/TR/html401/interact/forms.html#adef-readonly :

  • Los elementos de solo lectura reciben foco pero el usuario no puede modificarlos.
  • Los elementos de solo lectura se incluyen en la navegación por tabulación.
  • Los elementos de solo lectura pueden ser exitosos.

Cuando dice que el elemento puede tener éxito, significa que puede enviarse, como se indica aquí: http://www.w3.org/TR/html401/interact/forms.html#successful-controls

Phillip Whelan
fuente
66
El control NO está atenuado y el usuario PUEDE editarlo. No pudo leer la sección completa y cito: "Los siguientes elementos admiten el atributo de solo lectura: ENTRADA y TEXTAREA".
Carlos Rendon
3
Sé que esta es una respuesta antigua, pero en realidad funciona. No sé la razón de muchos votos negativos.
Ze Luis