¿Por qué los botones de radio no pueden ser "de solo lectura"?

213

Me gustaría mostrar un botón de opción, enviar su valor, pero dependiendo de las circunstancias, que no sea editable. Desactivar no funciona, porque no envía el valor (¿o sí?) Y atenúa el botón de opción. Solo lectura es realmente lo que estoy buscando, pero por alguna misteriosa razón no funciona.

¿Hay algún truco extraño que deba hacer para que solo la lectura funcione como se espera? ¿Debería hacerlo en JavaScript?

Por cierto, ¿alguien sabe por qué solo lectura no funciona en botones de radio, mientras que funciona en otras etiquetas de entrada? ¿Es esta una de esas omisiones incomprensibles en las especificaciones HTML?

mcv
fuente
55
"¿Es esta una de esas omisiones incomprensibles en las especificaciones HTML?" Piénselo desde el punto de vista del usuario. ¿Por qué mostrar un botón en el que no pueden hacer clic?
Paul D. Waite el
67
¿Por qué mostrar un botón en el que no pueden hacer clic? Porque quiero que sepan que el botón está allí, pero no quiero que puedan hacer clic en él ahora. Pero tal vez más tarde. Es una forma dinámica, después de todo. ¿Por qué un botón de radio sería diferente de cualquier otro campo de entrada?
mcv
77
Aquí está la especificación: w3.org/TR/html401/interact/forms.html#h-17.12.2 "Los siguientes elementos admiten el atributo de solo lectura: ENTRADA y TEXTAREA". Lo cual obviamente está mal. Sin embargo, aquí atrás, vemos un resumen más preciso: w3.org/TR/WD-forms-970402#readonly "READONLY se aplica a los elementos INPUT de tipo TEXT o PASSWORD y al elemento TEXTAREA". Parece que esto se ha deslizado entre los huecos de las grabaciones y especificaciones.
graphicdivine
Aún más curioso. De acuerdo con este antiguo documento "En las casillas de verificación, por ejemplo, puede activarlas o desactivarlas (configurando así el estado COMPROBADO) pero no cambia el valor del campo". ( htmlcodetutorial.com/forms/_INPUT_DISABLED.html ) ¿Es esto cierto? ¿Establecer READONLY en una casilla de verificación / radio bloquea el valor, aunque el usuario aparentemente puede alterarlo?
graphicdivine
revise mi publicación [aquí] [1] ofrece una solución simple y limpia al problema [1]: stackoverflow.com/a/15513256/1861389
driven4ward

Respuestas:

149

Fingí solo lectura en un botón de radio deshabilitando solo los botones de radio sin marcar. Evita que el usuario seleccione un valor diferente, y el valor marcado siempre se publicará al enviar.

Usando jQuery para hacer solo lectura:

$(':radio:not(:checked)').attr('disabled', true);

Este enfoque también funcionó para hacer una lista de selección de solo lectura, excepto que necesitará deshabilitar cada opción no seleccionada.

Megan
fuente
2
Gracias @Megan, esta es una gran solución
Michael La Voie
99
Una variación de esto para permitirle usar la readonlypropiedad, ya que el OP esperaba que funcionara:$(':radio[readonly]:not(:checked)').attr('disabled', true);
wodow
1
Entre las soluciones a continuación, esta solución proporciona el código más limpio y funciona bien con el validador Jquery, ya que no necesito habilitar / deshabilitar campos, ni tratar con eventos de clics no vinculantes y volver a vincularlos al enviar el formulario.
Kristianne Nerona
Funciona con precisión. Gracias
Hassan Farooq
¡Inteligente! Usando .not (..), en caso de que ya tenga un conjunto de campos de entrada seleccionados: var myRadios = $ ('# especifico-radios'); myRadios.not (': marcado'). prop ('deshabilitado', verdadero); api.jquery.com/not
JoePC
206

Los botones de opción solo tendrían que ser de solo lectura si hay otras opciones. Si no tiene otras opciones, un botón de opción marcado no se puede desmarcar. Si tiene otras opciones, puede evitar que el usuario cambie el valor simplemente deshabilitando las otras opciones:

<input type="radio" name="foo" value="Y" checked>
<input type="radio" name="foo" value="N" disabled>

Violín: http://jsfiddle.net/qqVGu/

Sampson
fuente
3
El problema con su primera solución es que si quiero habilitar el botón de radio a través de javascript, de repente tengo dos campos con el mismo nombre, así que tengo que limpiar uno de ellos. O use el oculto de verdad y haga que el botón de radio simplemente establezca el valor del campo oculto. De manera Ether, es un poco más engorroso de lo que me gustaría que fuera un botón de radio. Su segunda solución, aunque no dudo que funcione, suena como un truco realmente feo. Así que supongo que la solución de JavaScript es la única que cumple con mis criterios. Yo iré con eso.
mcv
77
Solución 1 por favor! Es el único accesible adecuadamente. Y si necesita escribir un guión, solo es una línea más para establecer la habilitación del campo oculto en el opuesto de la habilitación de la radio.
bobince
55
Acabo de notar que las soluciones 2 y 3 han cambiado de lugar en la respuesta de Jonathan, por lo que ahora los comentarios no parecen tener mucho sentido.
mcv
1
Quiere notar que la solución Javascript no funciona, solo desmarca el botón. Supongo que debe ser onclick="return false"para evitar el cambio.
dmitry
2
Cuando configuro la radio "deshabilitada", agrego "style = cursor: default" para eliminar "cursor deshabilitado".
Joao Paulo
24

Este es el truco con el que puedes ir.

<input type="radio" name="name" onclick="this.checked = false;" />
Sarfraz
fuente
44
Exactamente lo que estaba pensando, aunque sería mejor si aclarara que debería ser onClick="this.checked = <%=value%>"de alguna variedad :)
JustLoren
eso es genial saberlo. marcado puede tener valores verdaderos o falsos.
Sarfraz
Solo una advertencia de que esto no funcionará para aquellos de nosotros que navegamos con JavaScript no activado de forma predeterminada.
tloach
3
No es un problema para mi caso. Ya usamos toneladas de jQuery y Ajax.
mcv
1
Vale la pena señalar que solo puede hacer onclick="return false;"para mantener el valor igual para el grupo
Zach
12

Tengo un formulario largo (más de 250 campos) que se publica en una base de datos. Es una solicitud de empleo en línea. Cuando un administrador revisa una solicitud que se ha presentado, el formulario se llena con datos de la base de datos. Los textos de entrada y las áreas de texto se reemplazan con el texto que enviaron, pero las radios y las casillas de verificación son útiles para mantener como elementos de formulario. Deshabilitarlos los hace más difíciles de leer. Establecer la propiedad .checked en onclick falso no funcionará porque el usuario puede haberlos verificado al completar la aplicación. De todos modos...

onclick="return false;"

funciona de maravilla para 'deshabilitar' radios y casillas de verificación ipso facto.

luz humana
fuente
8

La mejor solución es establecer el estado marcado o no marcado (ya sea desde el cliente o el servidor) y no dejar que el usuario lo cambie después de las salas (es decir, que sea de solo lectura) haga lo siguiente:

<input type="radio" name="name" onclick="javascript: return false;" />
Vipresh
fuente
¡No! en este caso, el usuario puede editar html en el navegador, marcar la opción necesaria como seleccionada y publicar el formulario.
error1009
2

Se me ocurrió una forma de javascript pesado para lograr un estado de solo lectura para casillas de verificación y botones de radio. Se prueba con las versiones actuales de Firefox, Opera, Safari, Google Chrome, así como con las versiones actuales y anteriores de IE (hasta IE7).

¿Por qué no simplemente usar la propiedad para discapacitados que solicita? Al imprimir la página, los elementos de entrada deshabilitados aparecen en color gris. El cliente para el que se implementó esto quería que todos los elementos salieran del mismo color.

No estoy seguro de si se me permite publicar el código fuente aquí, ya que lo desarrollé mientras trabajaba para una empresa, pero seguramente puedo compartir los conceptos.

Con los eventos onmousedown, puede leer el estado de selección antes de que la acción de hacer clic lo cambie. Entonces almacena esta información y luego restaura estos estados con un evento onclick.

<input id="r1" type="radio" name="group1" value="r1" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 1</input>
<input id="r2" type="radio" name="group1" value="r2" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 2</input>
<input id="r3" type="radio" name="group1" value="r3" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 3</input>

<input id="c1" type="checkbox" name="group2" value="c1" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 1</input>
<input id="c2" type="checkbox" name="group2" value="c2" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 2</input>
<input id="c3" type="checkbox" name="group2" value="c3" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 3</input>

La parte de JavaScript de esto funcionaría así (nuevamente, solo los conceptos):

var selectionStore = new Object();  // keep the currently selected items' ids in a store

function storeSelectedRadiosForThisGroup(elementName) {
    // get all the elements for this group
    var radioOrSelectGroup = document.getElementsByName(elementName);

    // iterate over the group to find the selected values and store the selected ids in the selectionStore
    // ((radioOrSelectGroup[i].checked == true) tells you that)
    // remember checkbox groups can have multiple checked items, so you you might need an array for the ids
    ...
}

function setSelectedStateForEachElementOfThisGroup(elementName) {
    // iterate over the group and set the elements checked property to true/false, depending on whether their id is in the selectionStore
    ...

    // make sure you return false here
    return false;
}

Ahora puede habilitar / deshabilitar los botones de radio / casillas de verificación cambiando las propiedades onclick y onmousedown de los elementos de entrada.

Tom
fuente
2

Forma JavaScript: esto funcionó para mí.

<script>
$(document).ready(function() {
   $('#YourTableId').find('*').each(function () { $(this).attr("disabled", true); });
});
</script>

Razón:

  1. $('#YourTableId').find('*') -> esto devuelve todas las etiquetas.

  2. $('#YourTableId').find('*').each(function () { $(this).attr("disabled", true); }); itera sobre todos los objetos capturados en este y deshabilita las etiquetas de entrada.

Análisis (depuración):

  1. form:radiobutton se considera internamente como una etiqueta de "entrada".

  2. Al igual que en la función anterior (), si intenta imprimir document.write(this.tagName);

  3. Donde sea, en las etiquetas encuentra botones de radio, devuelve una etiqueta de entrada.

Por lo tanto, la línea de código anterior puede optimizarse más para las etiquetas de botón de radio, reemplazando * con entrada: $('#YourTableId').find('input').each(function () { $(this).attr("disabled", true); });

usuario3702798
fuente
1

Una opción bastante simple sería crear una función de JavaScript llamada en el evento "onsubmit" del formulario para habilitar el botón de radio de nuevo para que su valor se publique con el resto del formulario.
No parece ser una omisión en las especificaciones HTML, sino una opción de diseño (una lógica, en mi humilde opinión), un botón de radio no se puede leer solo como un botón, si no quieres usarlo, entonces deshabilitarlo

invierno
fuente
1

Encontré que el uso onclick='this.checked = false;'funcionó hasta cierto punto. No se seleccionaría un botón de radio en el que se hizo clic. Sin embargo, si había un botón de radio que ya estaba seleccionado (por ejemplo, un valor predeterminado), ese botón de radio quedaría sin seleccionar.

<!-- didn't completely work -->
<input type="radio" name="r1" id="r1" value="N" checked="checked" onclick='this.checked = false;'>N</input>
<input type="radio" name="r1" id="r1" value="Y" onclick='this.checked = false;'>Y</input>

Para este escenario, dejar solo el valor predeterminado e inhabilitar los otros botones de radio conserva el botón de radio ya seleccionado y evita que no se seleccione.

<!-- preserves pre-selected value -->
<input type="radio" name="r1" id="r1" value="N" checked="checked">N</input>
<input type="radio" name="r1" id="r1" value="Y" disabled>Y</input>

Esta solución no es la forma más elegante de evitar que se cambie el valor predeterminado, pero funcionará si JavaScript está habilitado o no.

JW8
fuente
1

Para los botones de radio no seleccionados, márquelos como deshabilitados. Esto evita que respondan a la entrada del usuario y borren el botón de radio marcado. Por ejemplo:

<input type="radio" name="var" checked="yes" value="Yes"></input>
<input type="radio" name="var" disabled="yes" value="No"></input>
dpolican
fuente
44
checked="yes"? ¿Qué especificación es esa? Utilice checked="checked"o simplemente el atributo checkedsin un valor. Lo mismo para disabled.
Robin van Baalen
1

Pruebe el atributo disabled, pero creo que no obtendrá el valor de los botones de opción. O establezca imágenes como:

<img src="itischecked.gif" alt="[x]" />radio button option

Atentamente.

Tim
fuente
1
oh, mi código html fue eliminado: img src = "itIsChecked.gif" alt = "[x]" OptionChecked
Tim
0

Estoy usando un complemento JS que da estilo a los elementos de entrada de radio / casilla de verificación y utilicé el siguiente jQuery para establecer un 'estado de solo lectura' donde el valor subyacente todavía se publica pero el elemento de entrada parece inaccesible para el usuario, lo cual creo que es la razón prevista usaríamos un atributo de entrada de solo lectura ...

if ($(node).prop('readonly')) {
    $(node).parent('div').addClass('disabled'); // just styling, appears greyed out
    $(node).on('click', function (e) {
        e.preventDefault();
    });
}
Chopstik
fuente