Estoy creando un nodo manualmente usando Vanilla JS. La idea es que esta alerta aparezca después de un campo de entrada si se ha alcanzado el límite de longitud máxima y se elimina si vuelve por debajo. Esto se usa en un CMS que los usuarios pueden usar para crear formularios dinámicamente, por lo que no sabré si el campo tendrá una longitud máxima o no, o si tendrá algo más después. Estoy usando el siguiente código:
document.querySelectorAll('input, textarea').forEach(element => { if (element.hasAttribute('maxlength')) { let maxChars = element.getAttribute('maxlength'); let elID = element.getAttribute('id'); let charWarning = document.querySelectorAll('#' + elID + ' + .char-limit'); element.addEventListener('input', () => { let inputLength = element.value.length; console.log(inputLength); if (inputLength >= maxChars) { if (charWarning.length == 0) { let divAlert = document.createElement('div'); let divAlertText = document.createTextNode(maxChars + ' character limit reached on input'); divAlert.classList.add('text-danger', 'char-limit'); divAlert.setAttribute('aria-live', 'polite'); divAlert.setAttribute('aria-labelledby', elID); divAlert.appendChild(divAlertText); element.insertAdjacentElement('afterend', divAlert); charWarning = document.querySelectorAll('#' + elID + ' + .char-limit'); } } else { // console.log(charWarning.length); if (charWarning.length > 0) { charWarning.remove(); // This is not working and I have no idea why. } } }); } });Por alguna razón, la función .remove() no funciona. Está arrojando un error:
charWarning.remove is not a function at HTMLTextAreaElementRealmente no entiendo esto. Pensé que podría deberse al hecho de que la configuración inicial de charWarning antes del oyente era estática, por lo que la agregué nuevamente al final de la función que crea el elemento de advertencia. Todo funciona bien, pero no elimina la advertencia cuando está por debajo de la longitud máxima y arroja ese error.
Para obtener información, el archivo console.log comentado:
// console.log(charWarning.length);Cuando no se comenta, devuelve 1, cuando se ha agregado el nodo.
¿Alguien puede señalar lo que estoy haciendo mal?
Ok, después de 2 días sin respuestas reales, volví a intentar esto a altas horas de la noche y de alguna manera lo descubrí a través de prueba y error. Pensé que el problema tenía que ver con el alcance, pero no pude averiguar QUÉ alcance. Al final, intenté cambiar "let" a "var" en la advertencia y eso no funcionó. Entonces cambié el selector de document.querySelectorAll a document.querySelector, limpié un poco el código y eliminé el resto usando encadenamiento condicional y voilà... ¡resultado! Mucho más limpio, mucho mejor (y lo más importante) código funcional...
Sin embargo, al investigar las propiedades de aria-live="polite" descubrí que crear y eliminar el nodo es un proceso incorrecto. Puedo crearlo, pero cuando quiero actualizarlo para tecnologías de asistencia, es el contenido lo que necesito cambiar. Esto se remonta al primer comentario de @ZainWilson-WCHStudent sobre mostrar y ocultar el contenido. Si bien todavía no estoy haciendo esto porque creo que es incorrecto para la accesibilidad, se apoya en esa idea. Creo que esta solución es mucho más elegante, eficiente y (lo más importante) accesible:
document.querySelectorAll("input, textarea").forEach((e) => { if (e.hasAttribute("maxlength")) { let maxChars = e.getAttribute("maxlength"); let elID = e.getAttribute("id"); let divAlert = document.createElement("div"); let divAlertText = document.createTextNode( maxChars + " character limit reached on input" ); divAlert.classList.add("text-danger", "char-limit"); divAlert.setAttribute("aria-live", "polite"); e.insertAdjacentElement("afterend", divAlert); e.addEventListener("input", () => { let charWarning = document.querySelector("#" + elID + " + .char-limit"); let inputLength = e.value.length; if (inputLength >= maxChars) { charWarning.appendChild(divAlertText); } else { if(charWarning.firstChild) { charWarning.removeChild(charWarning.firstChild); } } }); } });Aquí hay un Codepen para probar: https://codepen.io/tadywankenobi/pen/OJQXwwR