Esto, que parece una tonter铆a, no lo es en modo alguno. Cuando colocas un conjunto de botones de radio en una p谩gina Web con etiquetas de tipo <input type="radio">, al pulsar sobre cualquiera de ellos, 茅ste queda seleccionado. Al pulsar sobre cualquier otro del mismo grupo, el primero se deselecciona ya que s贸lo uno de ellos puede estar seleccionado al mismo tiempo. Este es el comportamiento normal y esperado. Sin embargo hay un problemilla que mucha gente se encuentra que con sorpresa no pueden solucionar: 驴qu茅 pasa si quieres desactivarlos todos una vez que ya hay alguno seleccionado?.

Prueba por ejemplo esta p谩gina. Al abrirla pulsa en los botones de radio de cualquiera de los grupos que contiene. Ahora intenta deseleccionarlos. No funciona.

Normalmente estos botones de radio se usan para dar a escoger entre varias opciones excluyentes entre s铆, pero tambi茅n puede darse la posibilidad de que la elecci贸n sea 'ninguna'. Lo que suele hacer la gente para solucionarlo es incluir un nuevo elemento en el grupo que sirva para indicar que no interesa ninguna de las otras, pero no deja de ser un apa帽o si lo que quieres en efecto es no tener ninguna seleccionada.

Si quieres solucionarlo puedes conseguirlo por c贸digo de una forma relativamente sencilla para un grupo de botones de radio. La soluci贸n consiste en llevar un registro del elemento que est谩 actualmente seleccionado y desactivarlo por c贸digo si es 茅ste el que se pulsa en un momento dado. No funciona la simple comprobaci贸n en el evento Click de si un elemento est谩 seleccionado o no, ya que ese evento Click salta justo despu茅s e haberse hecho el cambio, por lo que no tienes forma de determinar si realmente estaba o no seleccionado (pru茅balo, ver谩s que es un poco frustante).

A煤n as铆 lo mas complicado es poder gestionar esta capacidad para una p谩gina completa independientemente de cu谩ntos grupos de botones de radio existan en 茅sta.

Esto es precisamente lo que he hecho en esta otra p谩gina, para que el que se haya encontrado con este problema lo pueda solucionar. Si la visitas ver谩s que en ella la desactivaci贸n de los botones de radio funciona perfectamente y que s贸lo es necesario pulsar en uno que est茅 seleccionado para que se desactive.

Para conseguirlo hace falta un buen pu帽ado de JavaScript. 脡ste, adem谩s debe estar colocado despu茅s de todos los formularios de la p谩gina para que funcione. El motivo es que se realiza una inicializaci贸n dentro del c贸digo para la cual deben estar ya creados los contoles que se van a gestionar, y como sabemos los navegadores procesan los contenidos de las p谩ginas a medida que se los encuentran.

A continuaci贸n se expone el c贸digo necesario. 脡ste usa algunas cuestiones interesantes, como la generaci贸n din谩mica de variables en memoria as铆 como la comprobaci贸n de la existencia de 茅stas. Vamos a analizarlo:

<script type="text/javascript">
//Para distinguir la opci贸n actualmente pulsada en cada grupo
var pref_opcActual = "opcActual_";

//Verifica si una variable definida din谩micamente existe o no
function varExiste(sNombre)
{
    return (eval("typeof(" + sNombre + ");") != "undefined");
}

//Asigna un valor a una variable creada din谩micamente a partir de su nombre
function asignaVar(sNombre, valor)
{
    eval(sNombre + " = " + valor + ";");
}

//generamos din谩micamente variables globales para contener la opci贸n pulsada en cada uno de los grupos
for (f= 0; f<document.forms.length; f++)
{
  for (i = 0; i< document.forms[f].elements.length; i++)
  {
    var eltoAct = document.forms[f].elements[i];
    var exprCrearVariable = "";
    if (eltoAct.type == "radio")
    {
      //Si la variable no existe la definimos siempre,pero s贸lo la redefinimos en caso de que el elemento actual del grupo est茅 asignado
      if (!varExiste(pref_opcActual + eltoAct.name) ) 
        exprCrearVariable = "var " + pref_opcActual + eltoAct.name + " = ";
      else
        exprCrearVariable = pref_opcActual + eltoAct.name + " = ";
      
      //El valor ser谩 nulo o una referencia al radio actual en funci贸n de su est谩 seleccionado o no
      if(eltoAct.checked)
        exprCrearVariable += "document.getElementById('" + eltoAct.id + "')";
      else
        exprCrearVariable += "null";
        
      //Definimos la variable y asignamos el valor s贸lo si no existe o si el radio actual est谩 marcado 
      if ( !varExiste(pref_opcActual + eltoAct.name) || eltoAct.checked) 
        eval(exprCrearVariable);
    }
  }
}


function gestionarClickRadio(opcPulsada)
{
  //El nombre de la variable que contiene el nombre del grupo actual
  var svarOpcAct = pref_opcActual + opcPulsada.name;
  
  var opcActual = null;
  
  opcActual = eval(svarOpcAct);  //recupero din谩micamente una referencia al 煤ltimo radio pulsado de este grupo
  
    if (opcActual == opcPulsada)
    {
        opcPulsada.checked = false; //deselecciono
        asignaVar(svarOpcAct, "null");  //y quito referencia (es como si nunca se hubiera pulsado)
    }
    else
    {
    asignaVar(svarOpcAct, "document.getElementById('" + opcPulsada.id + "')");  //Anoto la 煤ltima opci贸n pulsada de este grupo
    }
}
</script>

El prefijo pref_opcActual se usar谩 para identificar la opci贸n seleccionada en cada una de los grupos de controles existentes en la p谩gina. Defino dos funciones auxiliares, varExiste y asignarVar, que sirven para comprobar que una variable dada cualquiera existe en la p谩gina actual y para asignar din帽amicamente un valor a una variables. Lo interesante de estas dos funciones es que permiten la comprobaci贸n y la asignaci贸n pasando simplemente una cadena con el nombre de la variable que nos interesa, la cual puede existir o no, y no es encesario pasar una referencia real a dicha variable. Esta caracter铆stica, habilitada por el m茅todo eval de JavaScript es muy interesante y no es utilizada muy a menudo por los programadores Web.

A continuaci贸n recorreo en un bucle cada uno de los posibles formularios que hay en la p谩gina (en ASP.NET uno solamente por regla general, pero esto funciona en cualqueir p谩gina) en busca de grupos de botones de radio.

Dentro del bucle para cada formulario lo que hago es generar din谩micamente, si no lo he hecho antes, el nombre de una variable por cada grupo de botones de radio. 脡sta se encargar谩 de almacenar din谩micamente una referencia al element actualmente seleccionado del grupo. Al terminar de ejecutarse el bucle lo que obtengo es una serie de variables llamadas opcActual_GrupoX, siendo GrupoX el nombre de cada grupo, las cuales contienen una referencia al elemento actualmente seleccionado en el grupo, de haberlo, o un nulo si no hay ninguno seleccionado en ese grupo.

N贸tese que el nombre del grupo es el valor del atributo Name de cada elemento input, y que 茅ste es el que se repite en los formularios apra defiinr los grupos. En un elemento input el atributo Name no tiene porque referirse realmente al nombre del elemento en la p谩gina (para eso est谩 el atributo Id) sino que es el nombre que se recibe en e帽 servidor una vez que se env铆a el formulario. En el caso de los botones de radio se env铆a s贸lo el valor de los que est谩n seleccionados, por eso todo se pueden llamar igual 8s贸lo hay uno seleccionado a la vez y por lo tanto s贸lo se env铆a un valor por cada grupo. Este es c贸digo HTML para definir un grupo de radios tipo con dos elementos:

<input type="radio" id="01" name="grupo" value="Opci贸n 1" onclick="gestionarClickRadio(this);"> Opci贸n 1<br>
<input type="radio" id="o2" name="grupo" value="Opci贸n 2" onclick="gestionarClickRadio(this);"> Opci贸n 2<br>

F铆jate que en neustro ejemplo, como queremos que se puedan deseleccionar las opciones, he incluido un gestor del evento click, eso s铆 gen茅rico, al que se le pasa simplemente una referencia al input que se ha pulsado (con this). Veaos qu茅 hace este manejador del evento click (f铆jate en el c贸digo JavaScript de arriba).

Lo primero es averiguar si hay alguna opci贸n de este grupo que ya est茅 previamente seleccionada. Recuerda que no vale comprobar en este momento el valor de la propiedad checked del elemento que se pulsa, ya que su estado habr谩 cambiado y no tene os forma de saber cu谩l era el estado anterior. Ante esta limitaci贸n lo que se hace es ver el valor de la variable din谩mica de tipo opcActual_ del grupo, que me devuelve una referencia al elemento que estaba seleccionado.

Si el elemento sobre el que hemo spulsado y a cuyo click estamos respondiendo coincide con el que ten铆amos registrado como seleccionado, entonces debemos desactivarlo. Adem谩s como ese es el 煤nico del grupo que pod铆a estar pulsado, guardamos como elemento actualmente seleccionado un nulo, ya que ya no habr谩 ninguno (era este y lo acabamos de desactivar).

Si no era el actual el elemento pulsado entonces dejamos que la "naturaleza siga su curso" y que se quede marcado. Eso s铆, anotamos el elemento actual como el seleccionado en nuestra variable opcActual_. Para ello evaluamos din谩micamente su identificador con getElementById (f铆jate en que es la 煤nica forma de hacerlo y que n se pasa realmente una referencia al mismo a asignaVar, sino una cadena con la expresi贸n que consigue evaluarlo).

Complicado 驴eh? :-)

Este es un excelente ejemplo de c贸mo una tarea aparentemente trivial puede ser bastante compleja de resolver y necesitaremos de t茅cnicas de programaci贸n m谩s o menos avanzadas para poder resolverla.

脡chale un buen repaso al c贸digo, ejec煤talo paso a paso con el depurador de Visual Studio y ver谩s que hay una l贸gica sencilla debajo de todo esto.

隆Espero que te sirva!

💪🏻 驴Este post te ha ayudado?, 驴has aprendido algo nuevo?
Pues NO te pido que me invites a un caf茅... Te pido algo m谩s f谩cil y mucho mejor