¿Por qué el checkbox se vuelve loco? Historia de un bug
\n\nImagine: está escribiendo un formulario de registro en un sitio web. Hay un checkbox "Acepto los términos". El usuario hace clic y la marca se coloca. Todo funciona. Luego decide agregar un botón "Marcar todos" con jQuery. Escribe $('#agree').attr('checked', true) y... no sucede nada. O la marca se coloca una vez, pero luego no se puede quitar. ¿Le suena familiar?
Esta pregunta es una de las más populares en Stack Overflow. Miles de desarrolladores tropiezan con la misma piedra. Y hoy entenderemos por qué sucede esto y cómo establecer correctamente checked para un checkbox con jQuery.
\n\nEn resumen: ¿cuál es el problema?
\n\nEl problema es que muchos principiantes (y no solo) usan el método .attr() para gestionar el atributo checked. Pero desde jQuery 1.6, la forma correcta es usar .prop(). La diferencia entre atributo (attribute) y propiedad (property) es un tema clave que vamos a desglosar.
Atributo vs Propiedad: ¿cuál es la diferencia?
\n\nVamos a explicarlo de forma sencilla. El atributo HTML es lo que escribe en el marcado:
\n\n<input type="checkbox" id="agree" checked>\n\nEl atributo checked aquí define el estado inicial del checkbox. Pero cuando el usuario hace clic, cambia la propiedad (property) del elemento DOM, mientras que el atributo permanece sin cambios.
El método .attr() trabaja con atributos, y .prop() con propiedades. Y como nos interesa el estado actual del checkbox (que cambia dinámicamente), necesitamos .prop().
Cómo se ve en el código
\n\nAquí hay un ejemplo simple que muestra la diferencia:
\n\n<!-- HTML -->\n<input type="checkbox" id="myCheckbox">\n<button id="setChecked">Marcar casilla</button>\n<button id="removeChecked">Desmarcar casilla</button>\n\n<script>\n// Forma correcta (jQuery 1.6+)\n$('#setChecked').click(function() {\n $('#myCheckbox').prop('checked', true);\n});\n\n$('#removeChecked').click(function() {\n $('#myCheckbox').prop('checked', false);\n});\n</script>\n\nTenga en cuenta: pasamos como segundo argumento true o false — un valor booleano. Esto es importante.
Errores típicos de principiantes (y cómo evitarlos)
\n\nError 1: Usar .attr() para establecer checked
\n\n// ❌ Incorrecto\n$('#myCheckbox').attr('checked', true);\n\n// ❌ También incorrecto\n$('#myCheckbox').attr('checked', 'checked');\n\n¿Por qué es malo? Porque .attr() establece el atributo, no la propiedad. Después del primer clic del usuario, el atributo puede permanecer, pero la propiedad cambia. El resultado es un comportamiento inconsistente.
Error 2: Pasar una cadena en lugar de un valor booleano
\n\n// ❌ Incorrecto\n$('#myCheckbox').prop('checked', 'true'); // cadena, no booleano\n\n¿jQuery convierte la cadena a booleano? En algunos casos, sí. Pero confiar en eso es una mala práctica. Siempre pase true o false sin comillas.
Error 3: Olvidar .prop() al leer el estado
\n\n// ❌ Incorrecto\nif ($('#myCheckbox').attr('checked')) { ... }\n\n// ✅ Correcto\nif ($('#myCheckbox').prop('checked')) { ... }\n\nPara leer el estado actual — solo .prop().
Ejemplo completo: formulario con checkboxes y botones de control
\n\nJuntemos todo. Imagine que tenemos una lista de opciones que el usuario puede seleccionar, y botones "Seleccionar todos" y "Deseleccionar todos".
\n\n<!DOCTYPE html>\n<html>\n<head>\n <title>Gestión de checkboxes con jQuery</title>\n <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>\n</head>\n<body>\n <h3